forked from xuos/xiuos
powerlink: build liboplkmn.a and liboplkcn.a
This commit is contained in:
parent
7e1307a3bb
commit
b7648f0f08
|
@ -1,3 +1,24 @@
|
|||
all: COMPILER
|
||||
|
||||
CUR_DIR := $(shell pwd)
|
||||
OPLK_ROOT := $(CUR_DIR)/openPOWERLINK
|
||||
LIBOPLKMN := $(OPLK_ROOT)/stack/lib/xiuos/arm/liboplkmn.a
|
||||
LIBOPLKCN := $(OPLK_ROOT)/stack/lib/xiuos/arm/liboplkcn.a
|
||||
LIBOPLK_BUILD_DIR := $(OPLK_ROOT)/stack/build/xiuos
|
||||
OPLK_TOOLCHAIN := $(OPLK_ROOT)/cmake/toolchain-xiuos-arm-none-eabi-gnu.cmake
|
||||
|
||||
.PHONY: $(LIBOPLKMN) $(LIBOPLKCN)
|
||||
$(LIBOPLKMN) $(LIBOPLKCN)&:
|
||||
cd $(LIBOPLK_BUILD_DIR) && \
|
||||
rm -rf CMakeFiles proj cmake_install.cmake CMakeCache.txt Makefile && \
|
||||
cmake -DCMAKE_TOOLCHAIN_FILE=$(OPLK_TOOLCHAIN) ../.. && \
|
||||
cmake --build . --target install
|
||||
|
||||
LIBOPLKMN := $(LIBOPLKMN:$(CUR_DIR)/%=%)
|
||||
LIBOPLKCN := $(LIBOPLKCN:$(CUR_DIR)/%=%)
|
||||
|
||||
SRC_FILES := $(LIBOPLKMN) $(LIBOPLKCN)
|
||||
|
||||
ifeq ($(CONFIG_CONNECTION_ADAPTER_ETHERCAT),y)
|
||||
SRC_DIR += ethercat
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
################################################################################
|
||||
#
|
||||
# CMake target configuration file for ARM XiUOS
|
||||
#
|
||||
# Copyright (c) 2016, Kalycito Infotech Pvt. Ltd.
|
||||
# Copyright (c) 2020, AIIT XUOS Lab
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the copyright holders nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
################################################################################
|
||||
|
||||
################################################################################
|
||||
# Name of the target platform
|
||||
SET(CMAKE_SYSTEM ARM-XiUOS)
|
||||
SET(CMAKE_SYSTEM_NAME XiUOS)
|
||||
SET(CMAKE_SYSTEM_PROCESSOR arm)
|
||||
|
||||
# specify the cross compiler
|
||||
SET(CMAKE_C_COMPILER arm-none-eabi-gcc)
|
||||
SET(CMAKE_CXX_COMPILER arm-none-eabi-g++)
|
||||
SET(CMAKE_ASM-ATT_COMPILER arm-none-eabi-as)
|
||||
|
||||
# skip CMake compiler check
|
||||
SET(CMAKE_C_COMPILER_WORKS TRUE)
|
||||
SET(CMAKE_CXX_COMPILER_WORKS TRUE)
|
||||
SET(CMAKE_ASM-ATT_COMPILER_WORKS TRUE)
|
||||
|
||||
# search for programs in the build host directories
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
# for libraries in the target directories
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER)
|
||||
# for headers in the target directories
|
||||
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER)
|
|
@ -4,6 +4,7 @@
|
|||
#
|
||||
# Copyright (c) 2014, B&R Industrial Automation GmbH
|
||||
# Copyright (c) 2016, Kalycito Infotech Private Limited
|
||||
# Copyright (c) 2020, AIIT XUOS Lab
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
@ -101,6 +102,8 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
|
|||
INCLUDE(cmake/options-linux.cmake)
|
||||
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "Windows")
|
||||
INCLUDE(cmake/options-windows.cmake)
|
||||
ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "XiUOS")
|
||||
INCLUDE(cmake/options-xiuos.cmake)
|
||||
ELSEIF((CMAKE_SYSTEM_NAME STREQUAL "Generic") AND (CMAKE_SYSTEM_PROCESSOR STREQUAL "Microblazeise"))
|
||||
INCLUDE(cmake/options-microblazeise.cmake)
|
||||
ELSEIF((CMAKE_SYSTEM_NAME STREQUAL "Generic") AND (CMAKE_SYSTEM_PROCESSOR STREQUAL "Microblaze"))
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
*
|
||||
.*
|
||||
!.gitignore
|
|
@ -0,0 +1,121 @@
|
|||
################################################################################
|
||||
#
|
||||
# CMake options for openPOWERLINK stack on XiUOS
|
||||
#
|
||||
# Copyright (c) 2016, B&R Industrial Automation GmbH
|
||||
# Copyright (c) 2016, Franz Profelt (franz.profelt@gmail.com)
|
||||
# Copyright (c) 2018, Kalycito Infotech Private Limited
|
||||
# Copyright (c) 2020, AIIT XUOS Lab
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the copyright holders nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
################################################################################
|
||||
|
||||
MESSAGE(STATUS "Adding CMAKE configuration options for XiUOS")
|
||||
|
||||
################################################################################
|
||||
# Options for MN libraries
|
||||
|
||||
OPTION (CFG_COMPILE_LIB_MN "Compile openPOWERLINK MN library" ON)
|
||||
OPTION (CFG_COMPILE_LIB_MNAPP_USERINTF "Compile openPOWERLINK MN application library for userspace" OFF)
|
||||
OPTION (CFG_COMPILE_LIB_MNAPP_KERNELINTF "Compile openPOWERLINK MN application library for kernel interface" OFF)
|
||||
OPTION (CFG_COMPILE_LIB_MNAPP_PCIEINTF "Compile openPOWERLINK MN application library for PCIe interface" OFF)
|
||||
OPTION (CFG_COMPILE_LIB_MNAPP_ZYNQINTF "Compile openPOWERLINK MN application library for zynq/FPGA interface" OFF)
|
||||
OPTION (CFG_COMPILE_LIB_MNDRV_PCAP "Compile openPOWERLINK MN driver library for linux userspace (pcap)" OFF)
|
||||
OPTION (CFG_COMPILE_LIB_MN_SIM "Compile openPOWERLINK MN library with simulation interface" OFF)
|
||||
|
||||
################################################################################
|
||||
# Options for CN libraries
|
||||
|
||||
OPTION (CFG_COMPILE_LIB_CN "Compile openPOWERLINK CN library" ON)
|
||||
OPTION (CFG_COMPILE_LIB_CNAPP_USERINTF "Compile openPOWERLINK CN application library for userspace" OFF)
|
||||
OPTION (CFG_COMPILE_LIB_CNAPP_KERNELINTF "Compile openPOWERLINK CN application library for kernel interface" OFF)
|
||||
OPTION (CFG_COMPILE_LIB_CNAPP_ZYNQINTF "Compile openPOWERLINK CN application library for zynq/FPGA interface" OFF)
|
||||
OPTION (CFG_COMPILE_LIB_CNDRV_PCAP "Compile openPOWERLINK CN driver library for linux userspace (pcap)" OFF)
|
||||
OPTION (CFG_COMPILE_LIB_CN_SIM "Compile openPOWERLINK CN library with simulation interface" OFF)
|
||||
|
||||
################################################################################
|
||||
# Options for shared libraries
|
||||
|
||||
OPTION (CFG_COMPILE_SHARED_LIBRARY "Build openPOWERLINK library as shared library" OFF)
|
||||
|
||||
################################################################################
|
||||
# Options for library features
|
||||
|
||||
OPTION (CFG_USE_PCAP_EDRV "Compile openPOWERLINK library with pcap edrv" OFF)
|
||||
OPTION (CFG_INCLUDE_MN_REDUNDANCY "Compile MN redundancy functions into MN libraries" OFF)
|
||||
CMAKE_DEPENDENT_OPTION (CFG_STORE_RESTORE "Support storing of OD in non-volatile memory (file system)" OFF
|
||||
"CFG_COMPILE_LIB_CN OR CFG_COMPILE_LIB_CNAPP_USERINTF OR CFG_COMPILE_LIB_CNAPP_KERNELINTF" OFF)
|
||||
|
||||
################################################################################
|
||||
# Add library subdirectories
|
||||
|
||||
# Add MN libraries
|
||||
IF(CFG_COMPILE_LIB_MN)
|
||||
ADD_SUBDIRECTORY(proj/xiuos/liboplkmn)
|
||||
ENDIF()
|
||||
|
||||
IF(CFG_COMPILE_LIB_MNAPP_USERINTF)
|
||||
ADD_SUBDIRECTORY(proj/linux/liboplkmnapp-userintf)
|
||||
ENDIF()
|
||||
|
||||
IF(CFG_COMPILE_LIB_MNAPP_KERNELINTF)
|
||||
ADD_SUBDIRECTORY(proj/linux/liboplkmnapp-kernelintf)
|
||||
ENDIF()
|
||||
|
||||
IF((CFG_COMPILE_LIB_MNAPP_PCIEINTF) OR (CFG_COMPILE_LIB_MNAPP_ZYNQINTF))
|
||||
ADD_SUBDIRECTORY(proj/linux/liboplkmnapp-kernelpcp)
|
||||
ENDIF()
|
||||
|
||||
IF(CFG_COMPILE_LIB_MNDRV_PCAP)
|
||||
ADD_SUBDIRECTORY(proj/linux/liboplkmndrv-pcap)
|
||||
ENDIF()
|
||||
|
||||
IF(CFG_COMPILE_LIB_MN_SIM)
|
||||
ADD_SUBDIRECTORY(proj/linux/liboplkmn-sim)
|
||||
ENDIF()
|
||||
|
||||
# Add CN libraries
|
||||
IF(CFG_COMPILE_LIB_CN)
|
||||
ADD_SUBDIRECTORY(proj/xiuos/liboplkcn)
|
||||
ENDIF()
|
||||
|
||||
IF(CFG_COMPILE_LIB_CNAPP_USERINTF)
|
||||
ADD_SUBDIRECTORY(proj/linux/liboplkcnapp-userintf)
|
||||
ENDIF()
|
||||
|
||||
IF(CFG_COMPILE_LIB_CNAPP_KERNELINTF)
|
||||
ADD_SUBDIRECTORY(proj/linux/liboplkcnapp-kernelintf)
|
||||
ENDIF()
|
||||
|
||||
IF(CFG_COMPILE_LIB_CNAPP_ZYNQINTF)
|
||||
ADD_SUBDIRECTORY(proj/linux/liboplkcnapp-kernelpcp)
|
||||
ENDIF()
|
||||
|
||||
IF(CFG_COMPILE_LIB_CNDRV_PCAP)
|
||||
ADD_SUBDIRECTORY(proj/linux/liboplkcndrv-pcap)
|
||||
ENDIF()
|
||||
|
||||
IF(CFG_COMPILE_LIB_CN_SIM)
|
||||
ADD_SUBDIRECTORY(proj/linux/liboplkcn-sim)
|
||||
ENDIF()
|
|
@ -5,6 +5,7 @@
|
|||
# Copyright (c) 2017, B&R Industrial Automation GmbH
|
||||
# Copyright (c) 2016, Franz Profelt (franz.profelt@gmail.com)
|
||||
# Copyright (c) 2018, Kalycito Infotech Private Limited
|
||||
# Copyright (c) 2020, AIIT XUOS Lab
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
|
@ -220,6 +221,11 @@ SET(EVENT_UCAL_LINUXUSER_SOURCES
|
|||
${USER_SOURCE_DIR}/event/eventucalintf-circbuf.c
|
||||
)
|
||||
|
||||
SET(EVENT_UCAL_XIUOS_SOURCES
|
||||
${USER_SOURCE_DIR}/event/eventucal-xiuos.c
|
||||
${USER_SOURCE_DIR}/event/eventucalintf-circbuf.c
|
||||
)
|
||||
|
||||
SET(EVENT_UCAL_LINUXIOCTL_SOURCES
|
||||
${USER_SOURCE_DIR}/event/eventucal-linuxioctl.c
|
||||
)
|
||||
|
@ -396,6 +402,11 @@ SET(EVENT_KCAL_WINDOWS_SOURCES
|
|||
${KERNEL_SOURCE_DIR}/event/eventkcalintf-circbuf.c
|
||||
)
|
||||
|
||||
SET(EVENT_KCAL_XIUOS_SOURCES
|
||||
${KERNEL_SOURCE_DIR}/event/eventkcal-xiuos.c
|
||||
${KERNEL_SOURCE_DIR}/event/eventkcalintf-circbuf.c
|
||||
)
|
||||
|
||||
SET(EVENT_KCAL_LINUXKERNEL_SOURCES
|
||||
${KERNEL_SOURCE_DIR}/event/eventkcal-linuxkernel.c
|
||||
${KERNEL_SOURCE_DIR}/event/eventkcalintf-circbuf.c
|
||||
|
@ -476,6 +487,13 @@ SET(HARDWARE_DRIVER_LINUXUSERRAWSOCKET_SOURCES
|
|||
${EDRV_SOURCE_DIR}/edrv-rawsock_linux.c
|
||||
)
|
||||
|
||||
SET(HARDWARE_DRIVER_XIUOS_SOURCES
|
||||
${KERNEL_SOURCE_DIR}/veth/veth-generic.c
|
||||
${KERNEL_SOURCE_DIR}/timer/hrestimer-xiuos.c
|
||||
${EDRV_SOURCE_DIR}/edrvcyclic.c
|
||||
${EDRV_SOURCE_DIR}/edrv-xiuos.c
|
||||
)
|
||||
|
||||
SET(HARDWARE_DRIVER_WINDOWS_SOURCES
|
||||
${EDRV_SOURCE_DIR}/edrvcyclic.c
|
||||
${EDRV_SOURCE_DIR}/edrv-pcap_win.c
|
||||
|
@ -533,6 +551,10 @@ SET(USER_TIMER_WINDOWS_SOURCES
|
|||
${USER_SOURCE_DIR}/timer/timer-generic.c
|
||||
)
|
||||
|
||||
SET(USER_TIMER_XIUOS_SOURCES
|
||||
${USER_SOURCE_DIR}/timer/timer-generic.c
|
||||
)
|
||||
|
||||
SET(USER_TIMER_GENERIC_SOURCES
|
||||
${USER_SOURCE_DIR}/timer/timer-generic.c
|
||||
)
|
||||
|
@ -643,6 +665,12 @@ ELSE ()
|
|||
)
|
||||
ENDIF ()
|
||||
|
||||
SET(TARGET_XIUOS_SOURCES
|
||||
${ARCH_SOURCE_DIR}/xiuos/target-xiuos.c
|
||||
${ARCH_SOURCE_DIR}/xiuos/target-mutex.c
|
||||
${ARCH_SOURCE_DIR}/xiuos/netif-xiuos.c
|
||||
)
|
||||
|
||||
SET(TARGET_MICROBLAZE_SOURCES
|
||||
${ARCH_SOURCE_DIR}/xilinx-microblaze/systemtimer.c
|
||||
${ARCH_SOURCE_DIR}/xilinx-microblaze/usleep.c
|
||||
|
|
|
@ -136,6 +136,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
#elif (defined (_WIN32) || defined (__MINGW32__))
|
||||
#define TARGET_SYSTEM _WIN32_ // WIN32 definition
|
||||
#define DEV_SYSTEM _DEV_WIN32_MINGW_
|
||||
#elif (defined(__XIUOS__)) // ARM / XiUOS
|
||||
#define TARGET_SYSTEM _XIUOS_
|
||||
#define DEV_SYSTEM _DEV_LINUX_
|
||||
#else /* (defined (_WIN32) || defined (__MINGW32__)) */ // unsupported
|
||||
#error 'ERROR: TARGET_SYSTEM / DEV_SYSTEM not found!'
|
||||
#endif
|
||||
|
@ -171,7 +174,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
//------------------------------------------------------------------------------
|
||||
// TARGET_SYSTEM specific definitions
|
||||
//------------------------------------------------------------------------------
|
||||
#if (TARGET_SYSTEM == _LINUX_)
|
||||
#if (TARGET_SYSTEM == _LINUX_ || TARGET_SYSTEM == _XIUOS_)
|
||||
|
||||
#include <oplk/targetdefs/linux.h>
|
||||
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
################################################################################
|
||||
#
|
||||
# CMake file for openPOWERLINK CN library on Linux userspace
|
||||
#
|
||||
# Copyright (c) 2017, B&R Industrial Automation GmbH
|
||||
# Copyright (c) 2020, AIIT XUOS Lab
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the copyright holders nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
################################################################################
|
||||
|
||||
# Set library name
|
||||
SET(LIB_NAME "oplkcn")
|
||||
MESSAGE(STATUS "Configuring ${LIB_NAME}")
|
||||
|
||||
# Set type of library
|
||||
IF(CFG_COMPILE_SHARED_LIBRARY)
|
||||
SET(LIB_TYPE "SHARED")
|
||||
ELSE()
|
||||
SET(LIB_TYPE "STATIC")
|
||||
ENDIF()
|
||||
|
||||
# set sources of POWERLINK library
|
||||
SET (LIB_SOURCES
|
||||
${USER_SOURCES}
|
||||
${CTRL_UCAL_DIRECT_SOURCES}
|
||||
${DLL_UCAL_CIRCBUF_SOURCES}
|
||||
${ERRHND_UCAL_LOCAL_SOURCES}
|
||||
${EVENT_UCAL_XIUOS_SOURCES}
|
||||
${PDO_UCAL_LOCAL_SOURCES}
|
||||
${USER_TIMER_XIUOS_SOURCES}
|
||||
${KERNEL_SOURCES}
|
||||
${CTRL_KCAL_DIRECT_SOURCES}
|
||||
${DLL_KCAL_CIRCBUF_SOURCES}
|
||||
${ERRHND_KCAL_LOCAL_SOURCES}
|
||||
${EVENT_KCAL_XIUOS_SOURCES}
|
||||
${PDO_KCAL_LOCAL_SOURCES}
|
||||
${COMMON_SOURCES}
|
||||
${COMMON_LINUXUSER_SOURCES}
|
||||
${TARGET_XIUOS_SOURCES}
|
||||
${OBD_CONF_LINUXUSER_SOURCES}
|
||||
${CIRCBUF_NOOS_SOURCES}
|
||||
${MEMMAP_NULL_SOURCES}
|
||||
${HARDWARE_DRIVER_XIUOS_SOURCES}
|
||||
)
|
||||
|
||||
# Configure compile definitions
|
||||
IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i.86|x86(_64)?)$")
|
||||
SET(LIB_SOURCES ${LIB_SOURCES} ${ARCH_X86_SOURCES})
|
||||
ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES arm*)
|
||||
SET(LIB_SOURCES ${LIB_SOURCES} ${ARCH_LE_SOURCES})
|
||||
ELSE()
|
||||
MESSAGE(FATAL_ERROR "Unsupported CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
ENDIF()
|
||||
|
||||
# Configure compile definitions
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -pedantic -std=c99 -fno-strict-aliasing")
|
||||
ADD_DEFINITIONS(-D__XIUOS__)
|
||||
ADD_DEFINITIONS(-D_GNU_SOURCE -D_POSIX_C_SOURCE=200112L)
|
||||
ADD_DEFINITIONS(-DCONFIG_FIND_LOCAL_INTERFACES)
|
||||
|
||||
IF(CFG_STORE_RESTORE)
|
||||
ADD_DEFINITIONS(-DCONFIG_INCLUDE_STORE_RESTORE)
|
||||
ENDIF()
|
||||
|
||||
# Additional include directories
|
||||
INCLUDE_DIRECTORIES(
|
||||
.
|
||||
)
|
||||
|
||||
# Define library and installation rules
|
||||
ADD_LIBRARY(${LIB_NAME} ${LIB_TYPE} ${LIB_SOURCES})
|
||||
TARGET_LINK_LIBRARIES(${LIB_NAME} ${ARCH_LIBRARIES})
|
||||
SET_PROPERTY(TARGET ${LIB_NAME} PROPERTY COMPILE_DEFINITIONS_DEBUG DEBUG;DEF_DEBUG_LVL=${CFG_DEBUG_LVL})
|
||||
SET_PROPERTY(TARGET ${LIB_NAME} PROPERTY DEBUG_POSTFIX "_d")
|
||||
INSTALL(TARGETS ${LIB_NAME} ARCHIVE DESTINATION . LIBRARY DESTINATION .)
|
|
@ -0,0 +1,134 @@
|
|||
/**
|
||||
********************************************************************************
|
||||
\file oplkcfg.h
|
||||
|
||||
\brief Configuration options for openPOWERLINK CN library
|
||||
|
||||
This file contains the configuration options for the openPOWERLINK CN libary
|
||||
on Linux.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
Copyright (c) 2012, SYSTEC electronik GmbH
|
||||
Copyright (c) 2018, B&R Industrial Automation GmbH
|
||||
Copyright (c) 2017, Kalycito Infotech Private Limited.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INC_oplkcfg_H_
|
||||
#define _INC_oplkcfg_H_
|
||||
|
||||
//==============================================================================
|
||||
// generic defines which for whole openPOWERLINK stack
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BENCHMARK_MODULES
|
||||
#define BENCHMARK_MODULES 0 //0xEE800042L
|
||||
#endif
|
||||
|
||||
// Default debug level:
|
||||
// Only debug traces of these modules will be compiled which flags are set in define DEF_DEBUG_LVL.
|
||||
#ifndef DEF_DEBUG_LVL
|
||||
#define DEF_DEBUG_LVL 0xC0000000L
|
||||
#endif
|
||||
|
||||
#undef FTRACE_DEBUG
|
||||
|
||||
/* assure that system priorities of hrtimer and net-rx kernel threads are set appropriate */
|
||||
#define CONFIG_THREAD_PRIORITY_HIGH 75
|
||||
#define CONFIG_THREAD_PRIORITY_MEDIUM 50
|
||||
#define CONFIG_THREAD_PRIORITY_LOW 49
|
||||
|
||||
// These macros define all modules which are included
|
||||
#define CONFIG_INCLUDE_PDO
|
||||
#define CONFIG_INCLUDE_SDOS
|
||||
#define CONFIG_INCLUDE_SDOC
|
||||
#define CONFIG_INCLUDE_SDO_ASND
|
||||
|
||||
#define CONFIG_DLLCAL_QUEUE CIRCBUF_QUEUE
|
||||
|
||||
#define CONFIG_VETH_SET_DEFAULT_GATEWAY FALSE
|
||||
|
||||
#define CONFIG_CHECK_HEARTBEAT_PERIOD 1000 // 1000 ms
|
||||
|
||||
//==============================================================================
|
||||
// Ethernet driver (Edrv) specific defines
|
||||
//==============================================================================
|
||||
|
||||
// switch this define to TRUE if Edrv supports auto delay responses
|
||||
#define CONFIG_EDRV_AUTO_RESPONSE_DELAY FALSE
|
||||
|
||||
// switch this define to TRUE to include Edrv diagnostic functions
|
||||
#define CONFIG_EDRV_USE_DIAGNOSTICS FALSE
|
||||
|
||||
//==============================================================================
|
||||
// Data Link Layer (DLL) specific defines
|
||||
//==============================================================================
|
||||
|
||||
// CN supports PRes Chaining
|
||||
#define CONFIG_DLL_PRES_CHAINING_CN FALSE
|
||||
|
||||
// negative time shift of isochronous task in relation to SoC
|
||||
#define CONFIG_DLL_SOC_SYNC_SHIFT_US 150
|
||||
|
||||
// time when CN processing the isochronous task (sync callback of application and cycle preparation)
|
||||
#define CONFIG_DLL_PROCESS_SYNC DLL_PROCESS_SYNC_ON_SOC
|
||||
|
||||
// Disable deferred release of rx-buffers until EdrvPcap supports it
|
||||
#define CONFIG_DLL_DEFERRED_RXFRAME_RELEASE_SYNC FALSE
|
||||
#define CONFIG_DLL_DEFERRED_RXFRAME_RELEASE_ASYNC FALSE
|
||||
|
||||
//==============================================================================
|
||||
// OBD specific defines
|
||||
//==============================================================================
|
||||
|
||||
// Switch this define to TRUE if the stack should check the object ranges
|
||||
#define CONFIG_OBD_CHECK_OBJECT_RANGE TRUE
|
||||
|
||||
// set this define to TRUE if there are strings or domains in OD, which
|
||||
// may be changed in object size and/or object data pointer by its object
|
||||
// callback function (called event kObdEvWrStringDomain)
|
||||
#define CONFIG_OBD_USE_STRING_DOMAIN_IN_RAM TRUE
|
||||
|
||||
// Set this string to true if OD configuration save and load feature is
|
||||
// supported by the device
|
||||
#ifdef CONFIG_INCLUDE_STORE_RESTORE
|
||||
#define CONFIG_OBD_USE_STORE_RESTORE TRUE
|
||||
#define CONFIG_OBD_CALC_OD_SIGNATURE TRUE
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
// Timer module specific defines
|
||||
//==============================================================================
|
||||
|
||||
// if TRUE the high resolution timer module will be used (must always be TRUE!)
|
||||
#define CONFIG_TIMER_USE_HIGHRES TRUE
|
||||
|
||||
//==============================================================================
|
||||
// SDO module specific defines
|
||||
//==============================================================================
|
||||
|
||||
#endif // _INC_oplkcfg_H_
|
|
@ -0,0 +1,95 @@
|
|||
################################################################################
|
||||
#
|
||||
# CMake file for openPOWERLINK MN library
|
||||
#
|
||||
# Copyright (c) 2017, B&R Industrial Automation GmbH
|
||||
# Copyright (c) 2020, AIIT XUOS Lab
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the copyright holders nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
################################################################################
|
||||
|
||||
# Set library name
|
||||
SET(LIB_NAME "oplkmn")
|
||||
MESSAGE(STATUS "Configuring ${LIB_NAME}")
|
||||
|
||||
# Set type of library
|
||||
IF(CFG_COMPILE_SHARED_LIBRARY)
|
||||
SET(LIB_TYPE "SHARED")
|
||||
ELSE()
|
||||
SET(LIB_TYPE "STATIC")
|
||||
ENDIF()
|
||||
|
||||
# set general sources of POWERLINK library
|
||||
SET (LIB_SOURCES
|
||||
${USER_SOURCES}
|
||||
${USER_MN_SOURCES}
|
||||
${CTRL_UCAL_DIRECT_SOURCES}
|
||||
${DLL_UCAL_CIRCBUF_SOURCES}
|
||||
${ERRHND_UCAL_LOCAL_SOURCES}
|
||||
${EVENT_UCAL_XIUOS_SOURCES}
|
||||
${PDO_UCAL_LOCAL_SOURCES}
|
||||
${USER_TIMER_XIUOS_SOURCES}
|
||||
${KERNEL_SOURCES}
|
||||
${CTRL_KCAL_DIRECT_SOURCES}
|
||||
${DLL_KCAL_CIRCBUF_SOURCES}
|
||||
${ERRHND_KCAL_LOCAL_SOURCES}
|
||||
${EVENT_KCAL_XIUOS_SOURCES}
|
||||
${PDO_KCAL_LOCAL_SOURCES}
|
||||
${COMMON_SOURCES}
|
||||
${COMMON_LINUXUSER_SOURCES}
|
||||
${TARGET_XIUOS_SOURCES}
|
||||
${CIRCBUF_NOOS_SOURCES}
|
||||
${MEMMAP_NULL_SOURCES}
|
||||
${HARDWARE_DRIVER_XIUOS_SOURCES}
|
||||
)
|
||||
|
||||
# Configure compile definitions
|
||||
IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i.86|x86(_64)?)$")
|
||||
SET(LIB_SOURCES ${LIB_SOURCES} ${ARCH_X86_SOURCES})
|
||||
ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES arm*)
|
||||
SET(LIB_SOURCES ${LIB_SOURCES} ${ARCH_LE_SOURCES})
|
||||
ELSE()
|
||||
MESSAGE(FATAL_ERROR "Unsupported CMAKE_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}")
|
||||
ENDIF()
|
||||
|
||||
# Configure compile definitions
|
||||
IF(CFG_INCLUDE_MN_REDUNDANCY)
|
||||
ADD_DEFINITIONS(-DCONFIG_INCLUDE_NMT_RMN)
|
||||
ENDIF()
|
||||
ADD_DEFINITIONS(-D__XIUOS__)
|
||||
ADD_DEFINITIONS(-DCONFIG_FIND_LOCAL_INTERFACES)
|
||||
ADD_DEFINITIONS(-DCONFIG_MN -D_GNU_SOURCE -D_POSIX_C_SOURCE=200112L)
|
||||
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -pedantic -std=c99 -fno-strict-aliasing")
|
||||
|
||||
# Additional include directories
|
||||
INCLUDE_DIRECTORIES(
|
||||
.
|
||||
)
|
||||
|
||||
# Define library and installation rules
|
||||
ADD_LIBRARY(${LIB_NAME} ${LIB_TYPE} ${LIB_SOURCES})
|
||||
TARGET_LINK_LIBRARIES(${LIB_NAME} ${ARCH_LIBRARIES})
|
||||
SET_PROPERTY(TARGET ${LIB_NAME} PROPERTY COMPILE_DEFINITIONS_DEBUG DEBUG;DEF_DEBUG_LVL=${CFG_DEBUG_LVL})
|
||||
SET_PROPERTY(TARGET ${LIB_NAME} PROPERTY DEBUG_POSTFIX "_d")
|
||||
INSTALL(TARGETS ${LIB_NAME} ARCHIVE DESTINATION . LIBRARY DESTINATION .)
|
|
@ -0,0 +1,141 @@
|
|||
/**
|
||||
********************************************************************************
|
||||
\file oplkcfg.h
|
||||
|
||||
\brief Configuration options for openPOWERLINK MN library
|
||||
|
||||
This file contains the configuration options for the openPOWERLINK MN libary
|
||||
on Linux.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
Copyright (c) 2012, SYSTEC electronik GmbH
|
||||
Copyright (c) 2018, B&R Industrial Automation GmbH
|
||||
Copyright (c) 2017, Kalycito Infotech Private Limited.
|
||||
Copyright (c) 2020, AIIT XUOS Lab
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef _INC_oplkcfg_H_
|
||||
#define _INC_oplkcfg_H_
|
||||
|
||||
//==============================================================================
|
||||
// generic defines which for whole openPOWERLINK stack
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BENCHMARK_MODULES
|
||||
#define BENCHMARK_MODULES 0 //0xEE800042L
|
||||
#endif
|
||||
|
||||
// Default debug level:
|
||||
// Only debug traces of these modules will be compiled which flags are set in define DEF_DEBUG_LVL.
|
||||
#ifndef DEF_DEBUG_LVL
|
||||
#define DEF_DEBUG_LVL 0xC0000000L
|
||||
#endif
|
||||
|
||||
#undef FTRACE_DEBUG
|
||||
|
||||
/* assure that system priorities of hrtimer and net-rx kernel threads are set appropriate */
|
||||
#define CONFIG_THREAD_PRIORITY_HIGH 75
|
||||
#define CONFIG_THREAD_PRIORITY_MEDIUM 50
|
||||
#define CONFIG_THREAD_PRIORITY_LOW 49
|
||||
|
||||
// These macros define all modules which are included
|
||||
#define CONFIG_INCLUDE_NMT_MN
|
||||
#define CONFIG_INCLUDE_PDO
|
||||
#define CONFIG_INCLUDE_SDOS
|
||||
#define CONFIG_INCLUDE_SDOC
|
||||
#define CONFIG_INCLUDE_SDO_ASND
|
||||
|
||||
#define CONFIG_DLLCAL_QUEUE CIRCBUF_QUEUE
|
||||
|
||||
#define CONFIG_VETH_SET_DEFAULT_GATEWAY FALSE
|
||||
|
||||
#define CONFIG_CHECK_HEARTBEAT_PERIOD 1000 // 1000 ms
|
||||
|
||||
//==============================================================================
|
||||
// Ethernet driver (Edrv) specific defines
|
||||
//==============================================================================
|
||||
|
||||
// switch this define to TRUE if Edrv supports auto delay responses
|
||||
#define CONFIG_EDRV_AUTO_RESPONSE_DELAY FALSE
|
||||
|
||||
// switch this define to TRUE to include Edrv diagnostic functions
|
||||
#define CONFIG_EDRV_USE_DIAGNOSTICS FALSE
|
||||
|
||||
//==============================================================================
|
||||
// Data Link Layer (DLL) specific defines
|
||||
//==============================================================================
|
||||
|
||||
// CN supports PRes Chaining
|
||||
#define CONFIG_DLL_PRES_CHAINING_CN FALSE
|
||||
|
||||
// time when CN processing the isochronous task (sync callback of application and cycle preparation)
|
||||
#define CONFIG_DLL_PROCESS_SYNC DLL_PROCESS_SYNC_ON_SOC
|
||||
|
||||
// Disable deferred release of rx-buffers until EdrvPcap supports it
|
||||
#define CONFIG_DLL_DEFERRED_RXFRAME_RELEASE_SYNC FALSE
|
||||
#define CONFIG_DLL_DEFERRED_RXFRAME_RELEASE_ASYNC FALSE
|
||||
|
||||
//==============================================================================
|
||||
// OBD specific defines
|
||||
//==============================================================================
|
||||
|
||||
// Switch this define to TRUE if the stack should check the object ranges
|
||||
#define CONFIG_OBD_CHECK_OBJECT_RANGE TRUE
|
||||
|
||||
// set this define to TRUE if there are strings or domains in OD, which
|
||||
// may be changed in object size and/or object data pointer by its object
|
||||
// callback function (called event kObdEvWrStringDomain)
|
||||
#define CONFIG_OBD_USE_STRING_DOMAIN_IN_RAM TRUE
|
||||
|
||||
#if defined(CONFIG_INCLUDE_CFM)
|
||||
#define CONFIG_OBD_DEF_CONCISEDCF_FILENAME "mnobd.cdc"
|
||||
#define CONFIG_CFM_CONFIGURE_CYCLE_LENGTH TRUE
|
||||
#endif
|
||||
|
||||
// Configure if the range from 0xA000 is used for mapping client objects.
|
||||
// openCONFIGURATOR uses this range for mapping objects.
|
||||
#define CONFIG_OBD_INCLUDE_A000_TO_DEVICE_PART TRUE
|
||||
|
||||
//==============================================================================
|
||||
// Timer module specific defines
|
||||
//==============================================================================
|
||||
|
||||
// if TRUE the high resolution timer module will be used (must always be TRUE!)
|
||||
#define CONFIG_TIMER_USE_HIGHRES TRUE
|
||||
|
||||
//==============================================================================
|
||||
// SDO module specific defines
|
||||
//==============================================================================
|
||||
|
||||
// increase the number of SDO channels, because we are master
|
||||
#define CONFIG_SDO_MAX_CONNECTION_ASND 100
|
||||
#define CONFIG_SDO_MAX_CONNECTION_SEQ 100
|
||||
#define CONFIG_SDO_MAX_CONNECTION_COM 100
|
||||
#define CONFIG_SDO_MAX_CONNECTION_UDP 50
|
||||
|
||||
#endif // _INC_oplkcfg_H_
|
|
@ -0,0 +1,122 @@
|
|||
/**
|
||||
********************************************************************************
|
||||
\file netif-linux.c
|
||||
|
||||
\brief Implementation of network interface enumeration functions for Linux
|
||||
|
||||
This file contains the implementation of helper functions for enumerating the
|
||||
network interfaces in Linux.
|
||||
|
||||
\ingroup module_target
|
||||
*******************************************************************************/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
Copyright (c) 2017, B&R Industrial Automation GmbH
|
||||
Copyright (c) 2020, AIIT XUOS Lab
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// includes
|
||||
//------------------------------------------------------------------------------
|
||||
#include <common/oplkinc.h>
|
||||
#include <common/target.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
//============================================================================//
|
||||
// G L O B A L D E F I N I T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// const defines
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// module global vars
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// global function prototypes
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
//============================================================================//
|
||||
// P R I V A T E D E F I N I T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// const defines
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local vars
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local function prototypes
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//============================================================================//
|
||||
// P U B L I C F U N C T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Enumerate network interfaces
|
||||
|
||||
This function enumerates all available network interfaces to be used by
|
||||
openPOWERLINK.
|
||||
|
||||
\param[out] pInterfaces_p Pointer to store the list of
|
||||
found interfaces.
|
||||
\param[in,out] pNoInterfaces_p Pointer to the number of interfaces.
|
||||
The maximum number of interfaces to be
|
||||
stored is passed to the function.
|
||||
The number of interfaces found is returned.
|
||||
|
||||
\return The function returns a \ref tOplkError error code.
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError target_enumerateNetworkInterfaces(tNetIfId* pInterfaces_p,
|
||||
size_t* pNoInterfaces_p)
|
||||
{
|
||||
UNUSED_PARAMETER(pInterfaces_p);
|
||||
UNUSED_PARAMETER(pNoInterfaces_p);
|
||||
return kErrorApiNotSupported;
|
||||
}
|
||||
|
||||
//============================================================================//
|
||||
// P R I V A T E F U N C T I O N S //
|
||||
//============================================================================//
|
||||
/// \name Private Functions
|
||||
/// \{
|
||||
|
||||
/// \}
|
|
@ -0,0 +1,196 @@
|
|||
/**
|
||||
********************************************************************************
|
||||
\file linux/target-mutex.c
|
||||
|
||||
\brief Architecture specific mutex implementation
|
||||
|
||||
This file contains the mutex implementation for Linux userspace. It uses
|
||||
BSD semaphores for the implementation and can therefore synchronize different
|
||||
threads or processes.
|
||||
|
||||
\ingroup module_target
|
||||
*******************************************************************************/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
Copyright (c) 2016, B&R Industrial Automation GmbH
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// includes
|
||||
//------------------------------------------------------------------------------
|
||||
#include <common/oplkinc.h>
|
||||
#include <common/target.h>
|
||||
|
||||
#include <fcntl.h> /* For O_* constants */
|
||||
#include <sys/stat.h> /* For mode constants */
|
||||
#include <semaphore.h>
|
||||
|
||||
//============================================================================//
|
||||
// G L O B A L D E F I N I T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// const defines
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// module global vars
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// global function prototypes
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//============================================================================//
|
||||
// P R I V A T E D E F I N I T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// const defines
|
||||
//------------------------------------------------------------------------------
|
||||
#define SEM_SHARED 0 // Mutex shared between threads of a process
|
||||
#define SEM_VALUE 1
|
||||
//------------------------------------------------------------------------------
|
||||
// local types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local vars
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local function prototypes
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//============================================================================//
|
||||
// P U B L I C F U N C T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Create Mutex
|
||||
|
||||
The function creates a mutex.
|
||||
|
||||
\param[in] mutexName_p The name of the mutex to create.
|
||||
\param[out] pMutex_p Pointer to store the created mutex.
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
\retval kErrorOk Mutex was successfully created.
|
||||
\retval kErrorNoFreeInstance An error occurred while creating the mutex.
|
||||
|
||||
\ingroup module_target
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError target_createMutex(const char* mutexName_p,
|
||||
OPLK_MUTEX_T* pMutex_p)
|
||||
{
|
||||
sem_t* pLockSem;
|
||||
|
||||
// WARNING: target_createMutex() will create a new independent mutex on each
|
||||
// call, even if the very same name is specified.
|
||||
UNUSED_PARAMETER(mutexName_p);
|
||||
|
||||
pLockSem = malloc(sizeof(sem_t));
|
||||
if (pLockSem != NULL)
|
||||
{
|
||||
if (sem_init(pLockSem, SEM_SHARED, SEM_VALUE) == 0)
|
||||
{
|
||||
*pMutex_p = pLockSem;
|
||||
return kErrorOk;
|
||||
}
|
||||
free(pLockSem);
|
||||
}
|
||||
return kErrorNoFreeInstance;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Destroy Mutex
|
||||
|
||||
The function destroys a mutex.
|
||||
|
||||
\param[in] mutexId_p The ID of the mutex to destroy.
|
||||
|
||||
\ingroup module_target
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
void target_destroyMutex(OPLK_MUTEX_T mutexId_p)
|
||||
{
|
||||
sem_t* pLockSem = (sem_t*)mutexId_p;
|
||||
if (pLockSem != NULL)
|
||||
{
|
||||
sem_destroy(pLockSem);
|
||||
free(mutexId_p);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Lock Mutex
|
||||
|
||||
The function locks a mutex.
|
||||
|
||||
\param[in] mutexId_p The ID of the mutex to lock.
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
\retval kErrorOk Mutex was successfully locked.
|
||||
\retval kErrorNoFreeInstance An error occurred while locking the mutex.
|
||||
|
||||
\ingroup module_target
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError target_lockMutex(OPLK_MUTEX_T mutexId_p)
|
||||
{
|
||||
if (sem_wait(mutexId_p) < 0)
|
||||
return kErrorIllegalInstance;
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Unlock Mutex
|
||||
|
||||
The function unlocks a mutex.
|
||||
|
||||
\param[in] mutexId_p The ID of the mutex to unlock.
|
||||
|
||||
\ingroup module_target
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
void target_unlockMutex(OPLK_MUTEX_T mutexId_p)
|
||||
{
|
||||
sem_post(mutexId_p);
|
||||
}
|
||||
|
||||
//============================================================================//
|
||||
// P R I V A T E F U N C T I O N S //
|
||||
//============================================================================//
|
||||
/// \name Private Functions
|
||||
/// \{
|
||||
|
||||
/// \}
|
|
@ -0,0 +1,381 @@
|
|||
/**
|
||||
********************************************************************************
|
||||
\file linux/target-linux.c
|
||||
|
||||
\brief Target specific functions for Linux
|
||||
|
||||
The file implements target specific functions used in the openPOWERLINK stack.
|
||||
|
||||
\ingroup module_target
|
||||
*******************************************************************************/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
Copyright (c) 2016, B&R Industrial Automation GmbH
|
||||
Copyright (c) 2018, Kalycito Infotech Private Limited
|
||||
Copyright (c) 2020, AIIT XUOS Lab
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// includes
|
||||
//------------------------------------------------------------------------------
|
||||
#include <common/oplkinc.h>
|
||||
#include <common/target.h>
|
||||
#include <common/ftracedebug.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <transform.h>
|
||||
|
||||
//============================================================================//
|
||||
// G L O B A L D E F I N I T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// const defines
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// module global vars
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// global function prototypes
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//============================================================================//
|
||||
// P R I V A T E D E F I N I T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// const defines
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local vars
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local function prototypes
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//============================================================================//
|
||||
// P U B L I C F U N C T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Initialize target specific stuff
|
||||
|
||||
The function initialize target specific stuff which is needed to run the
|
||||
openPOWERLINK stack.
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError target_init(void)
|
||||
{
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Clean up target specific stuff
|
||||
|
||||
The function cleans up target specific stuff.
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError target_cleanup(void)
|
||||
{
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Sleep for the specified number of milliseconds
|
||||
|
||||
The function makes the calling thread sleep until the number of specified
|
||||
milliseconds has elapsed.
|
||||
|
||||
\param[in] milliSeconds_p Number of milliseconds to sleep
|
||||
|
||||
\ingroup module_target
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
void target_msleep(UINT32 milliSeconds_p)
|
||||
{
|
||||
struct timeval timeout;
|
||||
fd_set readFds;
|
||||
int maxFd;
|
||||
int selectRetVal;
|
||||
unsigned int seconds;
|
||||
unsigned int microSeconds;
|
||||
|
||||
// initialize file descriptor set
|
||||
maxFd = 0 + 1;
|
||||
FD_ZERO(&readFds);
|
||||
|
||||
// Calculate timeout values
|
||||
seconds = milliSeconds_p / 1000;
|
||||
microSeconds = (milliSeconds_p - (seconds * 1000)) * 1000;
|
||||
|
||||
// initialize timeout value
|
||||
timeout.tv_sec = seconds;
|
||||
timeout.tv_usec = microSeconds;
|
||||
|
||||
selectRetVal = select(maxFd, &readFds, NULL, NULL, &timeout);
|
||||
switch (selectRetVal)
|
||||
{
|
||||
case 0: // select timeout occurred, no packet received
|
||||
break;
|
||||
|
||||
case -1: // select error occurred
|
||||
break;
|
||||
|
||||
default: // packet available for receive
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Set IP address of specified Ethernet interface
|
||||
|
||||
The function sets the IP address, subnetMask and MTU of an Ethernet
|
||||
interface.
|
||||
|
||||
\param[in] ifName_p Name of Ethernet interface.
|
||||
\param[in] ipAddress_p IP address to set for interface.
|
||||
\param[in] subnetMask_p Subnet mask to set for interface.
|
||||
\param[in] mtu_p MTU to set for interface.
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
|
||||
\ingroup module_target
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError target_setIpAdrs(const char* ifName_p,
|
||||
UINT32 ipAddress_p,
|
||||
UINT32 subnetMask_p,
|
||||
UINT16 mtu_p)
|
||||
{
|
||||
UNUSED_PARAMETER(ifName_p);
|
||||
UNUSED_PARAMETER(ipAddress_p);
|
||||
UNUSED_PARAMETER(subnetMask_p);
|
||||
UNUSED_PARAMETER(mtu_p);
|
||||
return kErrorApiNotSupported;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Set default gateway for Ethernet interface
|
||||
|
||||
The function sets the default gateway of an Ethernet interface.
|
||||
|
||||
\param[in] defaultGateway_p Default gateway to set.
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
|
||||
\ingroup module_target
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError target_setDefaultGateway(UINT32 defaultGateway_p)
|
||||
{
|
||||
UNUSED_PARAMETER(defaultGateway_p);
|
||||
return kErrorApiNotSupported;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Enables global interrupt
|
||||
|
||||
This function enables/disables global interrupts.
|
||||
|
||||
\param[in] fEnable_p TRUE = enable interrupts
|
||||
FALSE = disable interrupts
|
||||
|
||||
\note This function is implemented empty for the sim target
|
||||
\ingroup module_target
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
void target_enableGlobalInterrupt(BOOL fEnable_p)
|
||||
{
|
||||
UNUSED_PARAMETER(fEnable_p);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Set interrupt context flag
|
||||
|
||||
This function enables/disables the interrupt context flag. The flag has to be
|
||||
set when the CPU enters the interrupt context. The flag has to be cleared when
|
||||
the interrupt context is left.
|
||||
|
||||
\param[in] fEnable_p TRUE = enable interrupt context flag
|
||||
FALSE = disable interrupt context flag
|
||||
|
||||
\ingroup module_target
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
void target_setInterruptContextFlag(BOOL fEnable_p)
|
||||
{
|
||||
UNUSED_PARAMETER(fEnable_p);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Get interrupt context flag
|
||||
|
||||
This function returns the interrupt context flag.
|
||||
|
||||
\return The function returns the state of the interrupt context flag.
|
||||
|
||||
\ingroup module_target
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
BOOL target_getInterruptContextFlag(void)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Get current system tick
|
||||
|
||||
This function returns the current system tick determined by the system timer.
|
||||
|
||||
\return Returns the system tick in milliseconds
|
||||
|
||||
\ingroup module_target
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
UINT32 target_getTickCount(void)
|
||||
{
|
||||
return PrivGetTickTime();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Get current timestamp
|
||||
|
||||
The function returns the current timestamp in nanoseconds.
|
||||
|
||||
\return The function returns the timestamp in nanoseconds
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
ULONGLONG target_getCurrentTimestamp(void)
|
||||
{
|
||||
// Not implemented for this target
|
||||
return 0ULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Set POWERLINK status/error LED
|
||||
|
||||
The function sets the POWERLINK status/error LED.
|
||||
|
||||
\param[in] ledType_p Determines which LED shall be set/reset.
|
||||
\param[in] fLedOn_p Set the addressed LED on (TRUE) or off (FALSE).
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
|
||||
\ingroup module_target
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError target_setLed(tLedType ledType_p, BOOL fLedOn_p)
|
||||
{
|
||||
UNUSED_PARAMETER(ledType_p);
|
||||
UNUSED_PARAMETER(fLedOn_p);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
#if (defined(CONFIG_INCLUDE_SOC_TIME_FORWARD) && defined(CONFIG_INCLUDE_NMT_MN))
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Get system time
|
||||
|
||||
The function returns the current system timestamp.
|
||||
|
||||
\param[out] pNetTime_p Pointer to current system timestamp.
|
||||
\param[out] pValidSystemTime_p Pointer to flag which is set to indicate the
|
||||
system time is valid or not.
|
||||
|
||||
\return The function returns a tOplkError code.
|
||||
|
||||
\ingroup module_target
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError target_getSystemTime(tNetTime* pNetTime_p, BOOL* pValidSystemTime_p)
|
||||
{
|
||||
struct timespec currentTime;
|
||||
|
||||
if ((pNetTime_p == NULL) || (pValidSystemTime_p == NULL))
|
||||
return kErrorNoResource;
|
||||
|
||||
// Note: clock_gettime() returns 0 for success
|
||||
if (clock_gettime(CLOCK_REALTIME, ¤tTime) != 0)
|
||||
{
|
||||
*pValidSystemTime_p = FALSE;
|
||||
return kErrorGeneralError;
|
||||
}
|
||||
|
||||
if (currentTime.tv_sec < 0)
|
||||
{
|
||||
*pValidSystemTime_p = FALSE;
|
||||
DEBUG_LVL_ERROR_TRACE("%s(): Failed! Invalid time stamp.\n",
|
||||
__func__);
|
||||
return kErrorInvalidOperation;
|
||||
}
|
||||
|
||||
pNetTime_p->sec = currentTime.tv_sec;
|
||||
pNetTime_p->nsec = currentTime.tv_nsec;
|
||||
|
||||
// Set the flag to indicate the system time is valid
|
||||
*pValidSystemTime_p = TRUE;
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
#endif
|
||||
|
||||
//============================================================================//
|
||||
// P R I V A T E F U N C T I O N S //
|
||||
//============================================================================//
|
||||
/// \name Private Functions
|
||||
/// \{
|
||||
|
||||
/// \}
|
|
@ -0,0 +1,634 @@
|
|||
/**
|
||||
********************************************************************************
|
||||
\file edrv-xiuos.c
|
||||
|
||||
\brief Implementation of XiUOS Ethernet driver
|
||||
|
||||
This file contains the implementation of the XiUOS Ethernet driver.
|
||||
|
||||
\ingroup module_edrv
|
||||
*******************************************************************************/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
Copyright (c) 2017, BE.services GmbH
|
||||
Copyright (c) 2017, B&R Industrial Automation GmbH
|
||||
Copyright (c) 2020, AIIT XUOS Lab
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// includes
|
||||
//------------------------------------------------------------------------------
|
||||
#include <common/oplkinc.h>
|
||||
#include <common/ftracedebug.h>
|
||||
#include <kernel/edrv.h>
|
||||
#include <common/target.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <semaphore.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <xsconfig.h>
|
||||
|
||||
//============================================================================//
|
||||
// G L O B A L D E F I N I T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// const defines
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// module global vars
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// global function prototypes
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//============================================================================//
|
||||
// P R I V A T E D E F I N I T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// const defines
|
||||
//------------------------------------------------------------------------------
|
||||
#define EDRV_MAX_FRAME_SIZE 0x0600
|
||||
#define PROTO_PLK 0x88AB
|
||||
#ifndef PACKET_QDISC_BYPASS
|
||||
#define PACKET_QDISC_BYPASS 20
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
// local types
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Structure describing an instance of the Edrv
|
||||
|
||||
This structure describes an instance of the Ethernet driver.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
tEdrvInitParam initParam; ///< Init parameters
|
||||
tEdrvTxBuffer* pTransmittedTxBufferLastEntry; ///< Pointer to the last entry of the transmitted TX buffer
|
||||
tEdrvTxBuffer* pTransmittedTxBufferFirstEntry; ///< Pointer to the first entry of the transmitted Tx buffer
|
||||
pthread_mutex_t mutex; ///< Mutex for locking of critical sections
|
||||
sem_t syncSem; ///< Semaphore for signaling the start of the worker thread
|
||||
int sock; ///< Raw socket handle
|
||||
pthread_t hThread; ///< Handle of the worker thread
|
||||
BOOL fStartCommunication; ///< Flag to indicate, that communication is started. Set to false on exit
|
||||
BOOL fThreadIsExited; ///< Set by thread if already exited
|
||||
} tEdrvInstance;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local vars
|
||||
//------------------------------------------------------------------------------
|
||||
static tEdrvInstance edrvInstance_l;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local function prototypes
|
||||
//------------------------------------------------------------------------------
|
||||
static void packetHandler(void* pParam_p,
|
||||
const int frameSize_p,
|
||||
void* pPktData_p);
|
||||
static void* workerThread(void* pArgument_p);
|
||||
static void getMacAdrs(const char* pIfName_p, UINT8* pMacAddr_p);
|
||||
static BOOL getLinkStatus(const char* pIfName_p);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// XiUOS implementaion of raw socket
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//============================================================================//
|
||||
// P U B L I C F U N C T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Ethernet driver initialization
|
||||
|
||||
This function initializes the Ethernet driver.
|
||||
|
||||
\param[in] pEdrvInitParam_p Edrv initialization parameters
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
|
||||
\ingroup module_edrv
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError edrv_init(const tEdrvInitParam* pEdrvInitParam_p)
|
||||
{
|
||||
struct sched_param schedParam;
|
||||
|
||||
// Check parameter validity
|
||||
ASSERT(pEdrvInitParam_p != NULL);
|
||||
|
||||
// Clear instance structure
|
||||
OPLK_MEMSET(&edrvInstance_l, 0, sizeof(edrvInstance_l));
|
||||
|
||||
if (pEdrvInitParam_p->pDevName == NULL)
|
||||
return kErrorEdrvInit;
|
||||
|
||||
// Save the init data
|
||||
edrvInstance_l.initParam = *pEdrvInitParam_p;
|
||||
|
||||
edrvInstance_l.fStartCommunication = TRUE;
|
||||
edrvInstance_l.fThreadIsExited = FALSE;
|
||||
|
||||
// If no MAC address was specified read MAC address of used
|
||||
// Ethernet interface
|
||||
if ((edrvInstance_l.initParam.aMacAddr[0] == 0) &&
|
||||
(edrvInstance_l.initParam.aMacAddr[1] == 0) &&
|
||||
(edrvInstance_l.initParam.aMacAddr[2] == 0) &&
|
||||
(edrvInstance_l.initParam.aMacAddr[3] == 0) &&
|
||||
(edrvInstance_l.initParam.aMacAddr[4] == 0) &&
|
||||
(edrvInstance_l.initParam.aMacAddr[5] == 0))
|
||||
{ // read MAC address from controller
|
||||
getMacAdrs(edrvInstance_l.initParam.pDevName,
|
||||
edrvInstance_l.initParam.aMacAddr);
|
||||
}
|
||||
if (pthread_mutex_init(&edrvInstance_l.mutex, NULL) != 0)
|
||||
{
|
||||
DEBUG_LVL_ERROR_TRACE("%s() couldn't init mutex\n", __func__);
|
||||
return kErrorEdrvInit;
|
||||
}
|
||||
|
||||
edrvInstance_l.sock = open(ETHERNET_UART_NAME, O_RDWR);
|
||||
if (edrvInstance_l.sock < 0)
|
||||
{
|
||||
DEBUG_LVL_ERROR_TRACE("%s() cannot open socket. Error = %s\n", __func__, strerror(errno));
|
||||
return kErrorEdrvInit;
|
||||
}
|
||||
|
||||
if (sem_init(&edrvInstance_l.syncSem, 0, 0) != 0)
|
||||
{
|
||||
DEBUG_LVL_ERROR_TRACE("%s() couldn't init semaphore\n", __func__);
|
||||
return kErrorEdrvInit;
|
||||
}
|
||||
|
||||
if (pthread_create(&edrvInstance_l.hThread, NULL,
|
||||
workerThread, &edrvInstance_l) != 0)
|
||||
{
|
||||
DEBUG_LVL_ERROR_TRACE("%s() Couldn't create worker thread!\n", __func__);
|
||||
return kErrorEdrvInit;
|
||||
}
|
||||
|
||||
schedParam.sched_priority = CONFIG_THREAD_PRIORITY_MEDIUM;
|
||||
if (pthread_setschedparam(edrvInstance_l.hThread, SCHED_FIFO, &schedParam) != 0)
|
||||
{
|
||||
DEBUG_LVL_ERROR_TRACE("%s() couldn't set thread scheduling parameters!\n", __func__);
|
||||
}
|
||||
|
||||
#if (defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 12))
|
||||
pthread_setname_np(edrvInstance_l.hThread, "oplk-edrvrawsock");
|
||||
#endif
|
||||
|
||||
// wait until thread is started
|
||||
sem_wait(&edrvInstance_l.syncSem);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Shut down Ethernet driver
|
||||
|
||||
This function shuts down the Ethernet driver.
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
|
||||
\ingroup module_edrv
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError edrv_exit(void)
|
||||
{
|
||||
edrvInstance_l.fStartCommunication = FALSE;
|
||||
|
||||
// Wait to terminate thread safely
|
||||
usleep(100000);
|
||||
|
||||
if (edrvInstance_l.fThreadIsExited)
|
||||
pthread_cancel(edrvInstance_l.hThread);
|
||||
|
||||
pthread_mutex_destroy(&edrvInstance_l.mutex);
|
||||
|
||||
// Close the socket
|
||||
close(edrvInstance_l.sock);
|
||||
|
||||
// Clear instance structure
|
||||
OPLK_MEMSET(&edrvInstance_l, 0, sizeof(edrvInstance_l));
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Get MAC address
|
||||
|
||||
This function returns the MAC address of the Ethernet controller
|
||||
|
||||
\return The function returns a pointer to the MAC address.
|
||||
|
||||
\ingroup module_edrv
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
const UINT8* edrv_getMacAddr(void)
|
||||
{
|
||||
return edrvInstance_l.initParam.aMacAddr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Send Tx buffer
|
||||
|
||||
This function sends the Tx buffer.
|
||||
|
||||
\param[in,out] pBuffer_p Tx buffer descriptor
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
|
||||
\ingroup module_edrv
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError edrv_sendTxBuffer(tEdrvTxBuffer* pBuffer_p)
|
||||
{
|
||||
int sockRet;
|
||||
|
||||
// Check parameter validity
|
||||
ASSERT(pBuffer_p != NULL);
|
||||
|
||||
FTRACE_MARKER("%s", __func__);
|
||||
|
||||
if (pBuffer_p->txBufferNumber.pArg != NULL)
|
||||
return kErrorInvalidOperation;
|
||||
|
||||
if (getLinkStatus(edrvInstance_l.initParam.pDevName) == FALSE)
|
||||
{
|
||||
/* If there is no link, we pretend that the packet is sent and immediately call
|
||||
* tx handler. Otherwise the stack would hang! */
|
||||
if (pBuffer_p->pfnTxHandler != NULL)
|
||||
{
|
||||
pBuffer_p->pfnTxHandler(pBuffer_p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pthread_mutex_lock(&edrvInstance_l.mutex);
|
||||
if (edrvInstance_l.pTransmittedTxBufferLastEntry == NULL)
|
||||
{
|
||||
edrvInstance_l.pTransmittedTxBufferLastEntry = pBuffer_p;
|
||||
edrvInstance_l.pTransmittedTxBufferFirstEntry = pBuffer_p;
|
||||
}
|
||||
else
|
||||
{
|
||||
edrvInstance_l.pTransmittedTxBufferLastEntry->txBufferNumber.pArg = pBuffer_p;
|
||||
edrvInstance_l.pTransmittedTxBufferLastEntry = pBuffer_p;
|
||||
}
|
||||
pthread_mutex_unlock(&edrvInstance_l.mutex);
|
||||
|
||||
sockRet = write(edrvInstance_l.sock, (u_char*)pBuffer_p->pBuffer, (int)pBuffer_p->txFrameSize);
|
||||
if (sockRet < 0)
|
||||
{
|
||||
DEBUG_LVL_EDRV_TRACE("%s() send() returned %d\n", __func__, sockRet);
|
||||
return kErrorInvalidOperation;
|
||||
}
|
||||
else
|
||||
{
|
||||
packetHandler((u_char*)&edrvInstance_l, sockRet, pBuffer_p->pBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Allocate Tx buffer
|
||||
|
||||
This function allocates a Tx buffer.
|
||||
|
||||
\param[in,out] pBuffer_p Tx buffer descriptor
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
|
||||
\ingroup module_edrv
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError edrv_allocTxBuffer(tEdrvTxBuffer* pBuffer_p)
|
||||
{
|
||||
// Check parameter validity
|
||||
ASSERT(pBuffer_p != NULL);
|
||||
|
||||
if (pBuffer_p->maxBufferSize > EDRV_MAX_FRAME_SIZE)
|
||||
return kErrorEdrvNoFreeBufEntry;
|
||||
|
||||
// allocate buffer with malloc
|
||||
pBuffer_p->pBuffer = OPLK_MALLOC(pBuffer_p->maxBufferSize);
|
||||
if (pBuffer_p->pBuffer == NULL)
|
||||
return kErrorEdrvNoFreeBufEntry;
|
||||
|
||||
pBuffer_p->txBufferNumber.pArg = NULL;
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Free Tx buffer
|
||||
|
||||
This function releases the Tx buffer.
|
||||
|
||||
\param[in,out] pBuffer_p Tx buffer descriptor
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
|
||||
\ingroup module_edrv
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError edrv_freeTxBuffer(tEdrvTxBuffer* pBuffer_p)
|
||||
{
|
||||
void* pBuffer;
|
||||
|
||||
// Check parameter validity
|
||||
ASSERT(pBuffer_p != NULL);
|
||||
|
||||
pBuffer = pBuffer_p->pBuffer;
|
||||
|
||||
// mark buffer as free, before actually freeing it
|
||||
pBuffer_p->pBuffer = NULL;
|
||||
|
||||
OPLK_FREE(pBuffer);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Change Rx filter setup
|
||||
|
||||
This function changes the Rx filter setup. The parameter entryChanged_p
|
||||
selects the Rx filter entry that shall be changed and \p changeFlags_p determines
|
||||
the property.
|
||||
If \p entryChanged_p is equal or larger count_p all Rx filters shall be changed.
|
||||
|
||||
\note Rx filters are not supported by this driver!
|
||||
|
||||
\param[in,out] pFilter_p Base pointer of Rx filter array
|
||||
\param[in] count_p Number of Rx filter array entries
|
||||
\param[in] entryChanged_p Index of Rx filter entry that shall be changed
|
||||
\param[in] changeFlags_p Bit mask that selects the changing Rx filter property
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
|
||||
\ingroup module_edrv
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError edrv_changeRxFilter(tEdrvFilter* pFilter_p,
|
||||
UINT count_p,
|
||||
UINT entryChanged_p,
|
||||
UINT changeFlags_p)
|
||||
{
|
||||
UNUSED_PARAMETER(pFilter_p);
|
||||
UNUSED_PARAMETER(count_p);
|
||||
UNUSED_PARAMETER(entryChanged_p);
|
||||
UNUSED_PARAMETER(changeFlags_p);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Clear multicast address entry
|
||||
|
||||
This function removes the multicast entry from the Ethernet controller.
|
||||
|
||||
\note The multicast filters are not supported by this driver.
|
||||
|
||||
\param[in] pMacAddr_p Multicast address
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
|
||||
\ingroup module_edrv
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError edrv_clearRxMulticastMacAddr(const UINT8* pMacAddr_p)
|
||||
{
|
||||
UNUSED_PARAMETER(pMacAddr_p);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Set multicast address entry
|
||||
|
||||
This function sets a multicast entry into the Ethernet controller.
|
||||
|
||||
\note The multicast filters are not supported by this driver.
|
||||
|
||||
\param[in] pMacAddr_p Multicast address.
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
|
||||
\ingroup module_edrv
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError edrv_setRxMulticastMacAddr(const UINT8* pMacAddr_p)
|
||||
{
|
||||
UNUSED_PARAMETER(pMacAddr_p);
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//============================================================================//
|
||||
// P R I V A T E F U N C T I O N S //
|
||||
//============================================================================//
|
||||
/// \name Private Functions
|
||||
/// \{
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Edrv packet handler
|
||||
|
||||
This function is the packet handler forwarding the frames to the dllk.
|
||||
|
||||
\param[in,out] pParam_p User specific pointer pointing to the instance structure
|
||||
\param[in] frameSize_p Framesize information
|
||||
\param[in] pPktData_p Packet buffer
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
static void packetHandler(void* pParam_p,
|
||||
const int frameSize_p,
|
||||
void* pPktData_p)
|
||||
{
|
||||
tEdrvInstance* pInstance = (tEdrvInstance*)pParam_p;
|
||||
tEdrvRxBuffer rxBuffer;
|
||||
|
||||
if (OPLK_MEMCMP((UINT8*)pPktData_p + 6, pInstance->initParam.aMacAddr, 6) != 0)
|
||||
{ // filter out self generated traffic
|
||||
rxBuffer.bufferInFrame = kEdrvBufferLastInFrame;
|
||||
rxBuffer.rxFrameSize = frameSize_p;
|
||||
rxBuffer.pBuffer = pPktData_p;
|
||||
|
||||
FTRACE_MARKER("%s RX", __func__);
|
||||
pInstance->initParam.pfnRxHandler(&rxBuffer);
|
||||
}
|
||||
else
|
||||
{ // self generated traffic
|
||||
FTRACE_MARKER("%s TX-receive", __func__);
|
||||
|
||||
if (pInstance->pTransmittedTxBufferFirstEntry != NULL)
|
||||
{
|
||||
tEdrvTxBuffer* pTxBuffer = pInstance->pTransmittedTxBufferFirstEntry;
|
||||
|
||||
if (pTxBuffer->pBuffer != NULL)
|
||||
{
|
||||
if (OPLK_MEMCMP(pPktData_p, pTxBuffer->pBuffer, 6) == 0)
|
||||
{ // compare with packet buffer with destination MAC
|
||||
pthread_mutex_lock(&pInstance->mutex);
|
||||
pInstance->pTransmittedTxBufferFirstEntry = (tEdrvTxBuffer*)pInstance->pTransmittedTxBufferFirstEntry->txBufferNumber.pArg;
|
||||
if (pInstance->pTransmittedTxBufferFirstEntry == NULL)
|
||||
{
|
||||
pInstance->pTransmittedTxBufferLastEntry = NULL;
|
||||
}
|
||||
pthread_mutex_unlock(&pInstance->mutex);
|
||||
|
||||
pTxBuffer->txBufferNumber.pArg = NULL;
|
||||
|
||||
if (pTxBuffer->pfnTxHandler != NULL)
|
||||
{
|
||||
pTxBuffer->pfnTxHandler(pTxBuffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("%s: no matching TxB: DstMAC=%02X%02X%02X%02X%02X%02X\n",
|
||||
__func__,
|
||||
(UINT)((UINT8*)pPktData_p)[0],
|
||||
(UINT)((UINT8*)pPktData_p)[1],
|
||||
(UINT)((UINT8*)pPktData_p)[2],
|
||||
(UINT)((UINT8*)pPktData_p)[3],
|
||||
(UINT)((UINT8*)pPktData_p)[4],
|
||||
(UINT)((UINT8*)pPktData_p)[5]);
|
||||
TRACE(" current TxB %p: DstMAC=%02X%02X%02X%02X%02X%02X\n",
|
||||
(void*)pTxBuffer,
|
||||
(UINT)((UINT8*)(pTxBuffer->pBuffer))[0],
|
||||
(UINT)((UINT8*)(pTxBuffer->pBuffer))[1],
|
||||
(UINT)((UINT8*)(pTxBuffer->pBuffer))[2],
|
||||
(UINT)((UINT8*)(pTxBuffer->pBuffer))[3],
|
||||
(UINT)((UINT8*)(pTxBuffer->pBuffer))[4],
|
||||
(UINT)((UINT8*)(pTxBuffer->pBuffer))[5]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE("%s: no TxB: DstMAC=%02X%02X%02X%02X%02X%02X\n", __func__,
|
||||
((UINT8*)pPktData_p)[0],
|
||||
((UINT8*)pPktData_p)[1],
|
||||
((UINT8*)pPktData_p)[2],
|
||||
((UINT8*)pPktData_p)[3],
|
||||
((UINT8*)pPktData_p)[4],
|
||||
((UINT8*)pPktData_p)[5]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Edrv worker thread
|
||||
|
||||
This function implements the edrv worker thread. It is responsible to receive frames
|
||||
|
||||
\param[in,out] pArgument_p User specific pointer pointing to the instance structure
|
||||
|
||||
\return The function returns a thread error code.
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
static void* workerThread(void* pArgument_p)
|
||||
{
|
||||
tEdrvInstance* pInstance = (tEdrvInstance*)pArgument_p;
|
||||
int rawSockRet;
|
||||
u_char aBuffer[EDRV_MAX_FRAME_SIZE];
|
||||
|
||||
// signal that thread is successfully started
|
||||
sem_post(&pInstance->syncSem);
|
||||
|
||||
while (edrvInstance_l.fStartCommunication)
|
||||
{
|
||||
rawSockRet = read(edrvInstance_l.sock, aBuffer, EDRV_MAX_FRAME_SIZE);
|
||||
if (rawSockRet > 0)
|
||||
{
|
||||
packetHandler(pInstance, rawSockRet, aBuffer);
|
||||
}
|
||||
}
|
||||
edrvInstance_l.fThreadIsExited = TRUE;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Get Edrv MAC address
|
||||
|
||||
This function gets the interface's MAC address.
|
||||
|
||||
\param[in] pIfName_p Ethernet interface device name
|
||||
\param[out] pMacAddr_p Pointer to store MAC address
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
static void getMacAdrs(const char* pIfName_p, UINT8* pMacAddr_p)
|
||||
{
|
||||
UNUSED_PARAMETER(pIfName_p);
|
||||
|
||||
/* Generate a MAC address randomly */
|
||||
pMacAddr_p[0] = 0x52;
|
||||
pMacAddr_p[1] = 0x54;
|
||||
pMacAddr_p[2] = 0x98;
|
||||
pMacAddr_p[3] = 0x76;
|
||||
pMacAddr_p[4] = 0x54;
|
||||
pMacAddr_p[5] = target_getTickCount();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Get link status
|
||||
|
||||
This function returns the interface link status.
|
||||
|
||||
\param[in] pIfName_p Ethernet interface device name
|
||||
|
||||
\return The function returns the link status.
|
||||
\retval TRUE The link is up.
|
||||
\retval FALSE The link is down.
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
static BOOL getLinkStatus(const char* pIfName_p)
|
||||
{
|
||||
UNUSED_PARAMETER(pIfName_p);
|
||||
return TRUE;
|
||||
}
|
|
@ -0,0 +1,377 @@
|
|||
/**
|
||||
********************************************************************************
|
||||
\file eventkcal-linux.c
|
||||
|
||||
\brief Kernel event CAL module for Linux userspace
|
||||
|
||||
This file implements the kernel event handler CAL module for the Linux
|
||||
userspace platform. It uses the circular buffer interface for all event queues.
|
||||
|
||||
\see eventkcalintf-circbuf.c
|
||||
|
||||
\ingroup module_eventkcal
|
||||
*******************************************************************************/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
Copyright (c) 2016, B&R Industrial Automation GmbH
|
||||
Copyright (c) 2020, AIIT XUOS Lab
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// includes
|
||||
//------------------------------------------------------------------------------
|
||||
#include <common/oplkinc.h>
|
||||
#include <kernel/eventkcal.h>
|
||||
#include <kernel/eventkcalintf.h>
|
||||
#include <common/target.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <common/target.h>
|
||||
|
||||
//============================================================================//
|
||||
// G L O B A L D E F I N I T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// const defines
|
||||
//------------------------------------------------------------------------------
|
||||
#define KERNEL_EVENT_THREAD_PRIORITY 55
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// module global vars
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// global function prototypes
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//============================================================================//
|
||||
// P R I V A T E D E F I N I T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// const defines
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
\brief Kernel event CAL instance type
|
||||
|
||||
The structure contains all necessary information needed by the kernel event
|
||||
CAL module.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
pthread_t threadId;
|
||||
BOOL fStopThread;
|
||||
sem_t semUserData;
|
||||
sem_t semKernelData;
|
||||
BOOL fInitialized;
|
||||
} tEventkCalInstance;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local vars
|
||||
//------------------------------------------------------------------------------
|
||||
static tEventkCalInstance instance_l; ///< Instance variable of kernel event CAL module
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local function prototypes
|
||||
//------------------------------------------------------------------------------
|
||||
static void* eventThread(void* arg);
|
||||
static void signalKernelEvent(void);
|
||||
static void signalUserEvent(void);
|
||||
|
||||
//============================================================================//
|
||||
// P U B L I C F U N C T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Initialize kernel event CAL module
|
||||
|
||||
The function initializes the kernel event CAL module on Linux.
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
\retval kErrorOk Function executes correctly
|
||||
\retval other error codes An error occurred
|
||||
|
||||
\ingroup module_eventkcal
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError eventkcal_init(void)
|
||||
{
|
||||
struct sched_param schedParam;
|
||||
|
||||
OPLK_MEMSET(&instance_l, 0, sizeof(tEventkCalInstance));
|
||||
|
||||
if (sem_init(&instance_l.semUserData, 0, 0) < 0)
|
||||
goto Exit;
|
||||
|
||||
if (sem_init(&instance_l.semKernelData, 0, 0) < 0)
|
||||
goto Exit;
|
||||
|
||||
if (eventkcal_initQueueCircbuf(kEventQueueK2U) != kErrorOk)
|
||||
goto Exit;
|
||||
|
||||
if (eventkcal_initQueueCircbuf(kEventQueueU2K) != kErrorOk)
|
||||
goto Exit;
|
||||
|
||||
if (eventkcal_initQueueCircbuf(kEventQueueKInt) != kErrorOk)
|
||||
goto Exit;
|
||||
|
||||
eventkcal_setSignalingCircbuf(kEventQueueK2U, signalUserEvent);
|
||||
|
||||
eventkcal_setSignalingCircbuf(kEventQueueKInt, signalKernelEvent);
|
||||
|
||||
instance_l.fStopThread = FALSE;
|
||||
if (pthread_create(&instance_l.threadId, NULL, eventThread, (void*)&instance_l) != 0)
|
||||
goto Exit;
|
||||
|
||||
schedParam.sched_priority = KERNEL_EVENT_THREAD_PRIORITY;
|
||||
if (pthread_setschedparam(instance_l.threadId, SCHED_FIFO, &schedParam) != 0)
|
||||
{
|
||||
DEBUG_LVL_ERROR_TRACE("%s(): couldn't set thread scheduling parameters! %d\n",
|
||||
__func__,
|
||||
schedParam.sched_priority);
|
||||
}
|
||||
|
||||
#if (defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 12)
|
||||
pthread_setname_np(instance_l.threadId, "oplk-eventk");
|
||||
#endif
|
||||
|
||||
instance_l.fInitialized = TRUE;
|
||||
return kErrorOk;
|
||||
|
||||
Exit:
|
||||
if (instance_l.semUserData >= 0)
|
||||
sem_destroy(&instance_l.semUserData);
|
||||
|
||||
if (instance_l.semKernelData >= 0)
|
||||
sem_destroy(&instance_l.semKernelData);
|
||||
|
||||
eventkcal_exitQueueCircbuf(kEventQueueK2U);
|
||||
eventkcal_exitQueueCircbuf(kEventQueueU2K);
|
||||
eventkcal_exitQueueCircbuf(kEventQueueKInt);
|
||||
|
||||
return kErrorNoResource;
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Clean up kernel event CAL module
|
||||
|
||||
The function cleans up the kernel event CAL module. For cleanup it calls the exit
|
||||
functions of the queue implementations for each used queue.
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
\retval kErrorOk Function executes correctly
|
||||
\retval other error codes An error occurred
|
||||
|
||||
\ingroup module_eventkcal
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError eventkcal_exit(void)
|
||||
{
|
||||
UINT i = 0;
|
||||
|
||||
if (instance_l.fInitialized != FALSE)
|
||||
{
|
||||
instance_l.fStopThread = TRUE;
|
||||
while (instance_l.fStopThread != FALSE)
|
||||
{
|
||||
target_msleep(10);
|
||||
if (i++ > 100)
|
||||
{
|
||||
DEBUG_LVL_EVENTK_TRACE("Event thread is not terminating, continue shutdown...!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
eventkcal_exitQueueCircbuf(kEventQueueK2U);
|
||||
eventkcal_exitQueueCircbuf(kEventQueueU2K);
|
||||
eventkcal_exitQueueCircbuf(kEventQueueKInt);
|
||||
|
||||
sem_destroy(&instance_l.semUserData);
|
||||
sem_destroy(&instance_l.semKernelData);
|
||||
|
||||
sem_unlink("/semUserEvent");
|
||||
sem_unlink("/semKernelEvent");
|
||||
|
||||
}
|
||||
instance_l.fInitialized = FALSE;
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Post kernel event
|
||||
|
||||
This function posts a event to the kernel queue.
|
||||
|
||||
\param[in] pEvent_p Event to be posted.
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
\retval kErrorOk Function executes correctly
|
||||
\retval other error codes An error occurred
|
||||
|
||||
\ingroup module_eventkcal
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError eventkcal_postKernelEvent(const tEvent* pEvent_p)
|
||||
{
|
||||
tOplkError ret;
|
||||
|
||||
ret = eventkcal_postEventCircbuf(kEventQueueKInt, pEvent_p);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Post user event
|
||||
|
||||
This function posts a event to the user queue.
|
||||
|
||||
\param[in] pEvent_p Event to be posted.
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
\retval kErrorOk Function executes correctly
|
||||
\retval other error codes An error occurred
|
||||
|
||||
\ingroup module_eventkcal
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError eventkcal_postUserEvent(const tEvent* pEvent_p)
|
||||
{
|
||||
tOplkError ret;
|
||||
|
||||
ret = eventkcal_postEventCircbuf(kEventQueueK2U, pEvent_p);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Process function of kernel CAL module
|
||||
|
||||
This function will be called by the systems process function.
|
||||
|
||||
\ingroup module_eventkcal
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
void eventkcal_process(void)
|
||||
{
|
||||
// Nothing to do, because we use threads
|
||||
}
|
||||
|
||||
//============================================================================//
|
||||
// P R I V A T E F U N C T I O N S //
|
||||
//============================================================================//
|
||||
/// \name Private Functions
|
||||
/// \{
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Event handler thread function
|
||||
|
||||
This function contains the main function for the event handler thread.
|
||||
|
||||
\param[in,out] arg Thread parameter. Not used!
|
||||
|
||||
\return The function returns the thread exit code.
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
static void* eventThread(void* arg)
|
||||
{
|
||||
UINT32 tickCount;
|
||||
struct timespec curTime, timeout;
|
||||
tEventkCalInstance* pInstance = (tEventkCalInstance*)arg;
|
||||
|
||||
while (!pInstance->fStopThread)
|
||||
{
|
||||
tickCount = target_getTickCount();
|
||||
curTime.tv_sec = tickCount / 1000;
|
||||
curTime.tv_nsec = (tickCount % 1000) * 1000000;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_nsec = 50000 * 1000;
|
||||
TIMESPECADD(&timeout, &curTime);
|
||||
|
||||
if (sem_timedwait(&pInstance->semKernelData, &timeout) == 0)
|
||||
{
|
||||
/* first handle kernel internal events --> higher priority! */
|
||||
if (eventkcal_getEventCountCircbuf(kEventQueueKInt) > 0)
|
||||
{
|
||||
eventkcal_processEventCircbuf(kEventQueueKInt);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (eventkcal_getEventCountCircbuf(kEventQueueU2K) > 0)
|
||||
{
|
||||
eventkcal_processEventCircbuf(kEventQueueU2K);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pInstance->fStopThread = FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Signal a user event
|
||||
|
||||
This function signals that a user event was posted. It will be registered in
|
||||
the circular buffer library as signal callback function
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
static void signalUserEvent(void)
|
||||
{
|
||||
sem_post(&instance_l.semUserData);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Signal a kernel event
|
||||
|
||||
This function signals that a kernel event was posted. It will be registered in
|
||||
the circular buffer library as signal callback function
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
static void signalKernelEvent(void)
|
||||
{
|
||||
sem_post(&instance_l.semKernelData);
|
||||
}
|
||||
|
||||
/// \}
|
|
@ -0,0 +1,617 @@
|
|||
/**
|
||||
********************************************************************************
|
||||
\file hrestimer-xiuos.c
|
||||
|
||||
\brief High-resolution timer module for XiUOS
|
||||
|
||||
This module is the target specific implementation of the high-resolution
|
||||
timer module for XiUOS.
|
||||
|
||||
\ingroup module_hrestimer
|
||||
*******************************************************************************/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
Copyright (c) 2012, SYSTEC electronic GmbH
|
||||
Copyright (c) 2016, B&R Industrial Automation GmbH
|
||||
Copyright (c) 2020, AIIT XUOS Lab
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// includes
|
||||
//------------------------------------------------------------------------------
|
||||
#include <common/oplkinc.h>
|
||||
#include <common/ftracedebug.h>
|
||||
#include <common/target.h>
|
||||
#include <kernel/hrestimer.h>
|
||||
|
||||
#include <semaphore.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
|
||||
//============================================================================//
|
||||
// G L O B A L D E F I N I T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// const defines
|
||||
//------------------------------------------------------------------------------
|
||||
#undef HIGH_RESK_TIMER_LATENCY_DEBUG ///< enable/disable latency debugging
|
||||
|
||||
#define TIMER_COUNT 2 ///< number of high-resolution timers
|
||||
#define TIMER_MIN_VAL_SINGLE 20000 ///< minimum timer interval for single timeouts
|
||||
#define TIMER_MIN_VAL_CYCLE 100000 ///< minimum timer interval for continuous timeouts
|
||||
|
||||
/* macros for timer handles */
|
||||
#define TIMERHDL_MASK 0x0FFFFFFF
|
||||
#define TIMERHDL_SHIFT 28
|
||||
#define HDL_TO_IDX(hdl) ((hdl >> TIMERHDL_SHIFT) - 1)
|
||||
#define HDL_INIT(idx) ((idx + 1) << TIMERHDL_SHIFT)
|
||||
#define HDL_INC(hdl) (((hdl + 1) & TIMERHDL_MASK) | (hdl & ~TIMERHDL_MASK))
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// module global vars
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// global function prototypes
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//============================================================================//
|
||||
// P R I V A T E D E F I N I T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// const defines
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local types
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
\brief High-resolution timer information structure
|
||||
|
||||
The structure contains all necessary information for a high-resolution timer.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
tTimerEventArg eventArg; ///< Event argument
|
||||
tTimerkCallback pfnCallback; ///< Pointer to timer callback function
|
||||
struct timespec startTime; ///< Timestamp of timer start
|
||||
ULONGLONG time; ///< Timer period in nanoseconds
|
||||
pthread_t timerThreadId; ///< Handle of timer thread
|
||||
sem_t syncSem; ///< Thread synchronization semaphore
|
||||
BOOL fTerminate; ///< Thread termination flag
|
||||
BOOL fContinue; ///< Flag determines if timer will be restarted continuously
|
||||
#ifdef HIGH_RESK_TIMER_LATENCY_DEBUG
|
||||
/* additional variables for latency debugging */
|
||||
LONG maxLatency; ///< Minimum measured timer latency
|
||||
LONG minLatency; ///< Maximum measured timer latency
|
||||
#endif
|
||||
} tHresTimerInfo;
|
||||
|
||||
/**
|
||||
\brief High-resolution timer instance
|
||||
|
||||
The structure defines a high-resolution timer module instance.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
tHresTimerInfo aTimerInfo[TIMER_COUNT]; ///< Array with timer information for a set of timers
|
||||
} tHresTimerInstance;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// module local vars
|
||||
//------------------------------------------------------------------------------
|
||||
static tHresTimerInstance hresTimerInstance_l;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local function prototypes
|
||||
//------------------------------------------------------------------------------
|
||||
static void* timerThread(void* pArgument_p);
|
||||
static inline void timespec_add(const struct timespec* time1_p,
|
||||
ULONGLONG offset_p,
|
||||
struct timespec* result_p);
|
||||
|
||||
#ifdef HIGH_RESK_TIMER_LATENCY_DEBUG
|
||||
static inline void timespec_sub(const struct timespec* time1_p,
|
||||
const struct timespec* time2_p,
|
||||
struct timespec* result_p);
|
||||
#endif
|
||||
|
||||
|
||||
//============================================================================//
|
||||
// P U B L I C F U N C T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Initialize high-resolution timer module
|
||||
|
||||
The function initializes the high-resolution timer module
|
||||
|
||||
\return Returns a tOplkError error code.
|
||||
|
||||
\ingroup module_hrestimer
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError hrestimer_init(void)
|
||||
{
|
||||
tOplkError ret = kErrorOk;
|
||||
UINT index;
|
||||
struct sched_param schedParam;
|
||||
tHresTimerInfo* pTimerInfo;
|
||||
|
||||
OPLK_MEMSET(&hresTimerInstance_l, 0, sizeof(hresTimerInstance_l));
|
||||
|
||||
/* Initialize timer threads for all usable timers. */
|
||||
for (index = 0; index < TIMER_COUNT; index++)
|
||||
{
|
||||
pTimerInfo = &hresTimerInstance_l.aTimerInfo[index];
|
||||
pTimerInfo->fTerminate = FALSE;
|
||||
|
||||
#ifdef HIGH_RESK_TIMER_LATENCY_DEBUG
|
||||
pTimerInfo->maxLatency = 0;
|
||||
pTimerInfo->minLatency = 999999999;
|
||||
#endif
|
||||
|
||||
if (sem_init(&pTimerInfo->syncSem, 0, 0) != 0)
|
||||
{
|
||||
DEBUG_LVL_ERROR_TRACE("%s() Couldn't init semaphore!\n", __func__);
|
||||
return kErrorNoResource;
|
||||
}
|
||||
|
||||
if (pthread_create(&pTimerInfo->timerThreadId, NULL, timerThread, pTimerInfo) != 0)
|
||||
{
|
||||
sem_destroy(&pTimerInfo->syncSem);
|
||||
return kErrorNoResource;
|
||||
}
|
||||
|
||||
schedParam.sched_priority = CONFIG_THREAD_PRIORITY_HIGH;
|
||||
if (pthread_setschedparam(pTimerInfo->timerThreadId, SCHED_FIFO, &schedParam) != 0)
|
||||
{
|
||||
DEBUG_LVL_ERROR_TRACE("%s() Couldn't set thread scheduling parameters!\n", __func__);
|
||||
sem_destroy(&pTimerInfo->syncSem);
|
||||
pthread_cancel(pTimerInfo->timerThreadId);
|
||||
return kErrorNoResource;
|
||||
}
|
||||
|
||||
#if (defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 12))
|
||||
pthread_setname_np(pTimerInfo->timerThreadId, "oplk-hrtimer");
|
||||
#endif
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Shut down high-resolution timer module
|
||||
|
||||
The function shuts down the high-resolution timer module.
|
||||
|
||||
\return Returns a tOplkError error code.
|
||||
|
||||
\ingroup module_hrestimer
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError hrestimer_exit(void)
|
||||
{
|
||||
tHresTimerInfo* pTimerInfo;
|
||||
tOplkError ret = kErrorOk;
|
||||
UINT index;
|
||||
|
||||
for (index = 0; index < TIMER_COUNT; index++)
|
||||
{
|
||||
pTimerInfo = &hresTimerInstance_l.aTimerInfo[index];
|
||||
|
||||
pTimerInfo->eventArg.timerHdl.handle = 0;
|
||||
|
||||
/* send exit signal to thread */
|
||||
pTimerInfo->fContinue = 0;
|
||||
pTimerInfo->fTerminate = TRUE;
|
||||
sem_post(&pTimerInfo->syncSem);
|
||||
|
||||
/* wait until thread terminates */
|
||||
pthread_join(pTimerInfo->timerThreadId, NULL);
|
||||
|
||||
/* clean up */
|
||||
pTimerInfo->pfnCallback = NULL;
|
||||
sem_destroy(&pTimerInfo->syncSem);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Modify a high-resolution timer
|
||||
|
||||
The function modifies the timeout of the timer with the specified handle.
|
||||
If the handle to which the pointer points to is zero, the timer must be created
|
||||
first. If it is not possible to stop the old timer, this function always assures
|
||||
that the old timer does not trigger the callback function with the same handle
|
||||
as the new timer. That means the callback function must check the passed handle
|
||||
with the one returned by this function. If these are unequal, the call can be
|
||||
discarded.
|
||||
|
||||
\param[in,out] pTimerHdl_p Pointer to timer handle.
|
||||
\param[in] time_p Relative timeout in [ns].
|
||||
\param[in] pfnCallback_p Callback function, which is called when timer expires.
|
||||
(The function is called mutually exclusive with
|
||||
the Edrv callback functions (Rx and Tx)).
|
||||
\param[in] argument_p User-specific argument.
|
||||
\param[in] fContinue_p If TRUE, the callback function will be called continuously.
|
||||
Otherwise, it is a one-shot timer.
|
||||
|
||||
\return Returns a tOplkError error code.
|
||||
|
||||
\ingroup module_hrestimer
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError hrestimer_modifyTimer(tTimerHdl* pTimerHdl_p,
|
||||
ULONGLONG time_p,
|
||||
tTimerkCallback pfnCallback_p,
|
||||
ULONG argument_p,
|
||||
BOOL fContinue_p)
|
||||
{
|
||||
tOplkError ret = kErrorOk;
|
||||
UINT index;
|
||||
UINT32 tickCount;
|
||||
tHresTimerInfo* pTimerInfo;
|
||||
|
||||
DEBUG_LVL_TIMERH_TRACE("%s() pTimerHdl_p=%08x/%08x\n",
|
||||
__func__, (unsigned int)pTimerHdl_p, (unsigned int)*pTimerHdl_p);
|
||||
|
||||
if (pTimerHdl_p == NULL)
|
||||
return kErrorTimerInvalidHandle;
|
||||
|
||||
if (*pTimerHdl_p == 0)
|
||||
{ // no timer created yet
|
||||
// search free timer info structure
|
||||
pTimerInfo = &hresTimerInstance_l.aTimerInfo[0];
|
||||
for (index = 0; index < TIMER_COUNT; index++, pTimerInfo++)
|
||||
{
|
||||
if (pTimerInfo->eventArg.timerHdl.handle == 0)
|
||||
{ // free structure found
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (index >= TIMER_COUNT)
|
||||
{ // no free structure found
|
||||
return kErrorTimerNoTimerCreated;
|
||||
}
|
||||
|
||||
pTimerInfo->eventArg.timerHdl.handle = HDL_INIT(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
index = HDL_TO_IDX(*pTimerHdl_p);
|
||||
if (index >= TIMER_COUNT)
|
||||
{ // invalid handle
|
||||
return kErrorTimerInvalidHandle;
|
||||
}
|
||||
|
||||
pTimerInfo = &hresTimerInstance_l.aTimerInfo[index];
|
||||
}
|
||||
|
||||
// increase too small time values
|
||||
if (fContinue_p != FALSE)
|
||||
{
|
||||
if (time_p < TIMER_MIN_VAL_CYCLE)
|
||||
time_p = TIMER_MIN_VAL_CYCLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (time_p < TIMER_MIN_VAL_SINGLE)
|
||||
time_p = TIMER_MIN_VAL_SINGLE;
|
||||
}
|
||||
|
||||
/* increment timer handle
|
||||
* (if timer expires right after this statement, the user
|
||||
* would detect an unknown timer handle and discard it) */
|
||||
pTimerInfo->eventArg.timerHdl.handle = HDL_INC(pTimerInfo->eventArg.timerHdl.handle);
|
||||
*pTimerHdl_p = pTimerInfo->eventArg.timerHdl.handle;
|
||||
|
||||
/* initialize timer info */
|
||||
pTimerInfo->eventArg.argument.value = argument_p;
|
||||
pTimerInfo->pfnCallback = pfnCallback_p;
|
||||
pTimerInfo->fContinue = fContinue_p;
|
||||
pTimerInfo->time = time_p;
|
||||
|
||||
tickCount = target_getTickCount();
|
||||
pTimerInfo->startTime.tv_sec = tickCount / 1000;
|
||||
pTimerInfo->startTime.tv_nsec = (tickCount % 1000) * 1000000;
|
||||
sem_post(&pTimerInfo->syncSem); /* signal timer start to thread */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Delete a high-resolution timer
|
||||
|
||||
The function deletes a created high-resolution timer. The timer is specified
|
||||
by its timer handle. After deleting, the handle is reset to zero.
|
||||
|
||||
\param[in,out] pTimerHdl_p Pointer to timer handle.
|
||||
|
||||
\return Returns a tOplkError error code.
|
||||
|
||||
\ingroup module_hrestimer
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError hrestimer_deleteTimer(tTimerHdl* pTimerHdl_p)
|
||||
{
|
||||
tOplkError ret = kErrorOk;
|
||||
UINT index;
|
||||
tHresTimerInfo* pTimerInfo;
|
||||
|
||||
// check pointer to handle
|
||||
if (pTimerHdl_p == NULL)
|
||||
return kErrorTimerInvalidHandle;
|
||||
|
||||
if (*pTimerHdl_p == 0)
|
||||
{ // no timer created yet
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = HDL_TO_IDX(*pTimerHdl_p);
|
||||
if (index >= TIMER_COUNT)
|
||||
{ // invalid handle
|
||||
return kErrorTimerInvalidHandle;
|
||||
}
|
||||
pTimerInfo = &hresTimerInstance_l.aTimerInfo[index];
|
||||
if (pTimerInfo->eventArg.timerHdl.handle != *pTimerHdl_p)
|
||||
{ // invalid handle
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
pTimerInfo->fContinue = FALSE;
|
||||
*pTimerHdl_p = 0;
|
||||
pTimerInfo->eventArg.timerHdl.handle = 0;
|
||||
pTimerInfo->pfnCallback = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Control external synchronization interrupt
|
||||
|
||||
This function enables/disables the external synchronization interrupt. If the
|
||||
external synchronization interrupt is not supported, the call is ignored.
|
||||
|
||||
\param[in] fEnable_p Flag determines if sync should be enabled or disabled.
|
||||
|
||||
\ingroup module_hrestimer
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
void hrestimer_controlExtSyncIrq(BOOL fEnable_p)
|
||||
{
|
||||
UNUSED_PARAMETER(fEnable_p);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Set external synchronization interrupt time
|
||||
|
||||
This function sets the time when the external synchronization interrupt shall
|
||||
be triggered to synchronize the host processor. If the external synchronization
|
||||
interrupt is not supported, the call is ignored.
|
||||
|
||||
\param[in] time_p Time when the sync shall be triggered
|
||||
|
||||
\ingroup module_hrestimer
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
void hrestimer_setExtSyncIrqTime(tTimestamp time_p)
|
||||
{
|
||||
UNUSED_PARAMETER(time_p);
|
||||
}
|
||||
|
||||
//============================================================================//
|
||||
// P R I V A T E F U N C T I O N S //
|
||||
//============================================================================//
|
||||
/// \name Private Functions
|
||||
/// \{
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Timer thread function
|
||||
|
||||
The function provides the main function of the timer thread. It waits for a
|
||||
timer start signal. When it is received it reads the high-resolution timer
|
||||
information structure and calculates the timeout value. It sleeps by calling
|
||||
clock_nanosleep() until the timeout is reached. When the timeout is reached
|
||||
the callback function registered in the timer info structure is called. If the
|
||||
flag m_fContinue is set the thread loops until the timer is deleted.
|
||||
|
||||
\param[in,out] pArgument_p Thread parameter. It contains the pointer to
|
||||
the timer info structure.
|
||||
|
||||
\return Returns a void* as specified by the pthread interface but it is not used!
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
static void* timerThread(void* pArgument_p)
|
||||
{
|
||||
int iRet;
|
||||
tHresTimerInfo* pTimerInfo;
|
||||
struct timespec startTime, timeout;
|
||||
ULONGLONG period;
|
||||
tTimerHdl timerHdl;
|
||||
#ifdef HIGH_RESK_TIMER_LATENCY_DEBUG
|
||||
struct timespec debugtime, curTime;
|
||||
#endif
|
||||
|
||||
DEBUG_LVL_TIMERH_TRACE("%s(): ThreadId:%ld\n", __func__, syscall(SYS_gettid));
|
||||
DEBUG_LVL_TIMERH_TRACE("%s(): timer:%lx\n", __func__, (unsigned long)pArgument_p);
|
||||
|
||||
/* thread parameter contains the address of the timer information structure */
|
||||
pTimerInfo = (tHresTimerInfo*)pArgument_p;
|
||||
|
||||
/* loop forever until thread will be canceled */
|
||||
while (1)
|
||||
{
|
||||
/* wait for semaphore which signals a timer start */
|
||||
sem_wait(&pTimerInfo->syncSem);
|
||||
|
||||
/* check if thread should terminate */
|
||||
if (pTimerInfo->fTerminate)
|
||||
{
|
||||
DEBUG_LVL_TIMERH_TRACE("%s() Exiting signal received!\n", __func__);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* save timer information into local variables */
|
||||
startTime = pTimerInfo->startTime;
|
||||
timerHdl = pTimerInfo->eventArg.timerHdl.handle;
|
||||
period = pTimerInfo->time;
|
||||
|
||||
/* calculate the timeout value for the timer cycle */
|
||||
timespec_add(&startTime, period, &timeout);
|
||||
|
||||
#ifdef HIGH_RESK_TIMER_LATENCY_DEBUG
|
||||
clock_gettime(CLOCK_REALTIME, &curTime);
|
||||
#endif
|
||||
do
|
||||
{
|
||||
/* sleep until timeout */
|
||||
iRet = usleep(period / 1000);
|
||||
if (iRet < 0)
|
||||
{
|
||||
DEBUG_LVL_ERROR_TRACE("%s(): Error in clock_nanosleep!\n",
|
||||
__func__);
|
||||
/* todo how to signal that timeout wasn't correct? */
|
||||
}
|
||||
FTRACE_MARKER("HighReskTimer(%d) expired (%d ns)",
|
||||
(int)pArgument_p, period);
|
||||
|
||||
#ifdef HIGH_RESK_TIMER_LATENCY_DEBUG
|
||||
clock_gettime(CLOCK_REALTIME, &curTime);
|
||||
timespec_sub(&timeout, &curTime, &debugtime);
|
||||
FTRACE_MARKER("%s latency=%ld:%ld", __func__, debugtime.tv_sec,
|
||||
debugtime.tv_nsec);
|
||||
if (debugtime.tv_nsec > pTimerInfo->maxLatency)
|
||||
{
|
||||
DEBUG_LVL_TIMERH_TRACE("%s() Timer elapsed: max latency=%ld ns\n",
|
||||
__func__, debugtime.tv_nsec);
|
||||
pTimerInfo->maxLatency = debugtime.tv_nsec;
|
||||
}
|
||||
if (timeout.tv_nsec < pTimerInfo->minLatency)
|
||||
{
|
||||
DEBUG_LVL_TIMERH_TRACE("%s() Timer elapsed: min latency=%ld ns\n",
|
||||
__func__, debugtime.tv_nsec);
|
||||
pTimerInfo->minLatency = debugtime.tv_nsec;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* check if timer handle is valid */
|
||||
if (timerHdl == pTimerInfo->eventArg.timerHdl.handle)
|
||||
{
|
||||
/* call callback function */
|
||||
if (pTimerInfo->pfnCallback != NULL)
|
||||
{
|
||||
pTimerInfo->pfnCallback(&pTimerInfo->eventArg);
|
||||
}
|
||||
}
|
||||
|
||||
/* check if timer handle is still valid. Could be modified in callback! */
|
||||
if (timerHdl == pTimerInfo->eventArg.timerHdl.handle)
|
||||
{
|
||||
if (pTimerInfo->fContinue)
|
||||
{
|
||||
/* calculate timeout value for next timer cycle */
|
||||
timespec_add(&timeout, period, &timeout);
|
||||
}
|
||||
}
|
||||
} while ((pTimerInfo->fContinue) &&
|
||||
(timerHdl == pTimerInfo->eventArg.timerHdl.handle));
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Add offset to timespec value
|
||||
|
||||
The function adds a time offset in nanoseconds to a timespec value.
|
||||
|
||||
\param[in] time1_p Pointer to timespec to which the offset should be added.
|
||||
\param[in] offset_p Offset in nanoseconds to add.
|
||||
\param[out] result_p Pointer to store the result of the calculation.
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
static inline void timespec_add(const struct timespec* time1_p,
|
||||
ULONGLONG offset_p,
|
||||
struct timespec* result_p)
|
||||
{
|
||||
result_p->tv_sec = time1_p->tv_sec + offset_p / 1000000000L;
|
||||
result_p->tv_nsec = time1_p->tv_nsec + offset_p % 1000000000L;
|
||||
if (result_p->tv_nsec >= 1000000000L)
|
||||
{
|
||||
result_p->tv_sec++;
|
||||
result_p->tv_nsec -= 1000000000L;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HIGH_RESK_TIMER_LATENCY_DEBUG
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Subtract two timespec values
|
||||
|
||||
The function subtracts two timespec values.
|
||||
|
||||
\param[in] time1_p Pointer to first timespec value from which
|
||||
to substract the second one.
|
||||
\param[in] time2_p Pointer to second timespec value which will
|
||||
be substracted.
|
||||
\param[out] result_p Pointer to store the result of the calculation.
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
static inline void timespec_sub(const struct timespec* time1_p,
|
||||
const struct timespec* time2_p,
|
||||
struct timespec* result_p)
|
||||
{
|
||||
if (time2_p->tv_nsec > time1_p->tv_nsec)
|
||||
{
|
||||
result_p->tv_nsec = time2_p->tv_nsec - time1_p->tv_nsec;
|
||||
result_p->tv_sec = time2_p->tv_sec - time1_p->tv_sec;
|
||||
}
|
||||
else
|
||||
{
|
||||
result_p->tv_nsec = 1000000000L + time2_p->tv_nsec - time1_p->tv_nsec;
|
||||
result_p->tv_sec = time2_p->tv_sec - time1_p->tv_sec - 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// \}
|
|
@ -846,6 +846,8 @@ static tOplkError downloadCycleLength(tCfmNodeInfo* pNodeInfo_p)
|
|||
pNodeInfo_p->eventCnProgress.nodeId,
|
||||
ret);
|
||||
}
|
||||
#else
|
||||
UNUSED_PARAMETER(pNodeInfo_p);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -0,0 +1,379 @@
|
|||
/**
|
||||
********************************************************************************
|
||||
\file eventucal-linux.c
|
||||
|
||||
\brief User event CAL module for XiUOS
|
||||
|
||||
This file implements the user event handler CAL module for the Linux
|
||||
userspace platform. It uses the circular buffer interface for all event queues.
|
||||
|
||||
\see eventucalintf-circbuf.c
|
||||
|
||||
\ingroup module_eventucal
|
||||
*******************************************************************************/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
Copyright (c) 2016, B&R Industrial Automation GmbH
|
||||
Copyright (c) 2020, AIIT XUOS Lab
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// includes
|
||||
//------------------------------------------------------------------------------
|
||||
#include <common/oplkinc.h>
|
||||
#include <user/eventucal.h>
|
||||
#include <user/eventucalintf.h>
|
||||
#include <common/target.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <semaphore.h>
|
||||
#include <common/target.h>
|
||||
|
||||
//============================================================================//
|
||||
// G L O B A L D E F I N I T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// const defines
|
||||
//------------------------------------------------------------------------------
|
||||
#define USER_EVENT_THREAD_PRIORITY 45
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// module global vars
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// global function prototypes
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//============================================================================//
|
||||
// P R I V A T E D E F I N I T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// const defines
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local types
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief User event CAL instance type
|
||||
|
||||
The structure contains all necessary information needed by the user event
|
||||
CAL module.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
pthread_t threadId;
|
||||
BOOL fStopThread;
|
||||
sem_t semUserData;
|
||||
sem_t semKernelData;
|
||||
BOOL fInitialized;
|
||||
} tEventuCalInstance;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local vars
|
||||
//------------------------------------------------------------------------------
|
||||
static tEventuCalInstance instance_l; ///< Instance variable of user event CAL module
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// local function prototypes
|
||||
//------------------------------------------------------------------------------
|
||||
static void* eventThread(void* arg);
|
||||
static void signalUserEvent(void);
|
||||
static void signalKernelEvent(void);
|
||||
|
||||
//============================================================================//
|
||||
// P U B L I C F U N C T I O N S //
|
||||
//============================================================================//
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Initialize architecture specific stuff of user event CAL module
|
||||
|
||||
The function initializes the architecture specific stuff of the user event
|
||||
CAL module.
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
\retval kErrorOk Function executes correctly
|
||||
\retval other error codes An error occurred
|
||||
|
||||
\ingroup module_eventucal
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError eventucal_init(void)
|
||||
{
|
||||
struct sched_param schedParam;
|
||||
|
||||
OPLK_MEMSET(&instance_l, 0, sizeof(tEventuCalInstance));
|
||||
|
||||
if (sem_init(&instance_l.semUserData, 0, 0) < 0)
|
||||
goto Exit;
|
||||
|
||||
if (sem_init(&instance_l.semKernelData, 0, 0) < 0)
|
||||
goto Exit;
|
||||
|
||||
if (eventucal_initQueueCircbuf(kEventQueueK2U) != kErrorOk)
|
||||
goto Exit;
|
||||
|
||||
if (eventucal_initQueueCircbuf(kEventQueueU2K) != kErrorOk)
|
||||
goto Exit;
|
||||
|
||||
eventucal_setSignalingCircbuf(kEventQueueU2K, signalKernelEvent);
|
||||
|
||||
if (eventucal_initQueueCircbuf(kEventQueueUInt) != kErrorOk)
|
||||
goto Exit;
|
||||
|
||||
eventucal_setSignalingCircbuf(kEventQueueUInt, signalUserEvent);
|
||||
|
||||
instance_l.fStopThread = FALSE;
|
||||
if (pthread_create(&instance_l.threadId, NULL, eventThread, (void*)&instance_l) != 0)
|
||||
goto Exit;
|
||||
|
||||
schedParam.sched_priority = USER_EVENT_THREAD_PRIORITY;
|
||||
if (pthread_setschedparam(instance_l.threadId, SCHED_FIFO, &schedParam) != 0)
|
||||
{
|
||||
DEBUG_LVL_ERROR_TRACE("%s(): couldn't set thread scheduling parameters! %d\n",
|
||||
__func__,
|
||||
schedParam.sched_priority);
|
||||
}
|
||||
|
||||
#if (defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 12))
|
||||
pthread_setname_np(instance_l.threadId, "oplk-eventu");
|
||||
#endif
|
||||
|
||||
instance_l.fInitialized = TRUE;
|
||||
return kErrorOk;
|
||||
|
||||
Exit:
|
||||
if (instance_l.semUserData >= 0)
|
||||
sem_destroy(&instance_l.semUserData);
|
||||
|
||||
if (instance_l.semKernelData >= 0)
|
||||
sem_destroy(&instance_l.semKernelData);
|
||||
|
||||
eventucal_exitQueueCircbuf(kEventQueueK2U);
|
||||
eventucal_exitQueueCircbuf(kEventQueueU2K);
|
||||
eventucal_exitQueueCircbuf(kEventQueueUInt);
|
||||
|
||||
return kErrorNoResource;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Clean up kernel event CAL module
|
||||
|
||||
The function cleans up the kernel event CAL module. For cleanup it calls the exit
|
||||
functions of the queue implementations for each used queue.
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
\retval kErrorOk Function executes correctly
|
||||
\retval other error codes An error occurred
|
||||
|
||||
\ingroup module_eventucal
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError eventucal_exit(void)
|
||||
{
|
||||
UINT i = 0;
|
||||
|
||||
if (instance_l.fInitialized != FALSE)
|
||||
{
|
||||
instance_l.fStopThread = TRUE;
|
||||
while (instance_l.fStopThread != FALSE)
|
||||
{
|
||||
target_msleep(10);
|
||||
if (i++ > 100)
|
||||
{
|
||||
DEBUG_LVL_EVENTU_TRACE("%s(): Event thread is not terminating, continue shutdown...!\n",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
eventucal_exitQueueCircbuf(kEventQueueK2U);
|
||||
eventucal_exitQueueCircbuf(kEventQueueU2K);
|
||||
eventucal_exitQueueCircbuf(kEventQueueUInt);
|
||||
|
||||
sem_destroy(&instance_l.semUserData);
|
||||
sem_destroy(&instance_l.semKernelData);
|
||||
}
|
||||
instance_l.fInitialized = FALSE;
|
||||
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Post kernel event
|
||||
|
||||
This function posts an event to a queue. It is called from the generic kernel
|
||||
event post function in the event handler. Depending on the sink the appropriate
|
||||
queue post function is called.
|
||||
|
||||
\param[in] pEvent_p Event to be posted.
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
\retval kErrorOk Function executes correctly
|
||||
\retval other error codes An error occurred
|
||||
|
||||
\ingroup module_eventucal
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError eventucal_postKernelEvent(const tEvent* pEvent_p)
|
||||
{
|
||||
tOplkError ret;
|
||||
|
||||
// Check parameter validity
|
||||
ASSERT(pEvent_p != NULL);
|
||||
|
||||
ret = eventucal_postEventCircbuf(kEventQueueU2K, pEvent_p);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Post user event
|
||||
|
||||
This function posts an event to a queue. It is called from the generic kernel
|
||||
event post function in the event handler. Depending on the sink the appropriate
|
||||
queue post function is called.
|
||||
|
||||
\param[in] pEvent_p Event to be posted.
|
||||
|
||||
\return The function returns a tOplkError error code.
|
||||
\retval kErrorOk Function executes correctly
|
||||
\retval other error codes An error occurred
|
||||
|
||||
\ingroup module_eventucal
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
tOplkError eventucal_postUserEvent(const tEvent* pEvent_p)
|
||||
{
|
||||
tOplkError ret;
|
||||
|
||||
// Check parameter validity
|
||||
ASSERT(pEvent_p != NULL);
|
||||
|
||||
ret = eventucal_postEventCircbuf(kEventQueueUInt, pEvent_p);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Process function of user CAL module
|
||||
|
||||
This function will be called by the system process function.
|
||||
|
||||
\ingroup module_eventucal
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
void eventucal_process(void)
|
||||
{
|
||||
// Nothing to do, because we use threads
|
||||
}
|
||||
|
||||
//============================================================================//
|
||||
// P R I V A T E F U N C T I O N S //
|
||||
//============================================================================//
|
||||
/// \name Private Functions
|
||||
/// \{
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Event handler thread function
|
||||
|
||||
This function contains the main function for the event handler thread.
|
||||
|
||||
\param[in,out] arg Thread parameter. Used to access the module instance.
|
||||
|
||||
\return The function returns the thread exit code.
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
static void* eventThread(void* arg)
|
||||
{
|
||||
UINT32 tickCount;
|
||||
struct timespec curTime, timeout;
|
||||
tEventuCalInstance* pInstance = (tEventuCalInstance*)arg;
|
||||
|
||||
while (!pInstance->fStopThread)
|
||||
{
|
||||
tickCount = target_getTickCount();
|
||||
curTime.tv_sec = tickCount / 1000;
|
||||
curTime.tv_nsec = (tickCount % 1000) * 1000000;
|
||||
timeout.tv_sec = 0;
|
||||
timeout.tv_nsec = 50000 * 1000;
|
||||
TIMESPECADD(&timeout, &curTime);
|
||||
|
||||
if (sem_timedwait(&pInstance->semUserData, &timeout) == 0)
|
||||
{
|
||||
/* first handle all user to kernel events --> higher priority! */
|
||||
if (eventucal_getEventCountCircbuf(kEventQueueK2U) > 0)
|
||||
eventucal_processEventCircbuf(kEventQueueK2U);
|
||||
else
|
||||
{
|
||||
if (eventucal_getEventCountCircbuf(kEventQueueUInt) > 0)
|
||||
eventucal_processEventCircbuf(kEventQueueUInt);
|
||||
}
|
||||
}
|
||||
}
|
||||
pInstance->fStopThread = FALSE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Signal a user event
|
||||
|
||||
This function signals that a user event has been posted. It will be registered
|
||||
in the circular buffer library as signal callback function.
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
static void signalUserEvent(void)
|
||||
{
|
||||
sem_post(&instance_l.semUserData);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
\brief Signal a kernel event
|
||||
|
||||
This function signals that a kernel event has been posted. It will be registered
|
||||
in the circular buffer library as signal callback function.
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
static void signalKernelEvent(void)
|
||||
{
|
||||
sem_post(&instance_l.semKernelData);
|
||||
}
|
||||
|
||||
/// \}
|
|
@ -63,6 +63,11 @@ extern "C" {
|
|||
typedef int pid_t;
|
||||
// typedef int pthread_mutex_t ;
|
||||
|
||||
/* scheduling algorithms */
|
||||
#define SCHED_OTHER 0
|
||||
#define SCHED_FIFO 1
|
||||
#define SCHED_RR 2
|
||||
|
||||
/* function in pthread.c */
|
||||
int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void));
|
||||
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||
|
|
|
@ -34,7 +34,7 @@ menu "aiit-arm32-board feature"
|
|||
endmenu
|
||||
|
||||
menu "config hardware resources for connection"
|
||||
if CONNECTION_COMMUNICATION_ETHERNET
|
||||
if CONNECTION_INDUSTRIAL_ETHERNET
|
||||
config ETHERNET_UART_NAME
|
||||
string "ethernet uart name"
|
||||
default "/dev/usart3_dev3"
|
||||
|
|
|
@ -36,7 +36,7 @@ menu "aiit-riscv64-board feature"
|
|||
endmenu
|
||||
|
||||
menu "config hardware resources for connection"
|
||||
if CONNECTION_COMMUNICATION_ETHERNET
|
||||
if CONNECTION_INDUSTRIAL_ETHERNET
|
||||
config ETHERNET_UART_NAME
|
||||
string "ethernet uart name"
|
||||
default "/dev/uart3_dev3"
|
||||
|
|
|
@ -34,7 +34,7 @@ menu "cortex-m4-emulator feature"
|
|||
endmenu
|
||||
|
||||
menu "config hardware resources for connection"
|
||||
if CONNECTION_COMMUNICATION_ETHERNET
|
||||
if CONNECTION_INDUSTRIAL_ETHERNET
|
||||
config ETHERNET_UART_NAME
|
||||
string "ethernet uart name"
|
||||
default "/dev/usart3_dev3"
|
||||
|
|
|
@ -35,7 +35,7 @@ menu "gapuino feature"
|
|||
endmenu
|
||||
|
||||
menu "config hardware resources for connection"
|
||||
if CONNECTION_COMMUNICATION_ETHERNET
|
||||
if CONNECTION_INDUSTRIAL_ETHERNET
|
||||
config ETHERNET_UART_NAME
|
||||
string "ethernet uart name"
|
||||
default "/dev/uart3_dev3"
|
||||
|
|
|
@ -45,7 +45,7 @@ menu "kd233 feature"
|
|||
endmenu
|
||||
|
||||
menu "config hardware resources for connection"
|
||||
if CONNECTION_COMMUNICATION_ETHERNET
|
||||
if CONNECTION_INDUSTRIAL_ETHERNET
|
||||
config ETHERNET_UART_NAME
|
||||
string "ethernet uart name"
|
||||
default "/dev/uart3_dev3"
|
||||
|
|
|
@ -45,7 +45,7 @@ menu "kd233 feature"
|
|||
endmenu
|
||||
|
||||
menu "config hardware resources for connection"
|
||||
if CONNECTION_COMMUNICATION_ETHERNET
|
||||
if CONNECTION_INDUSTRIAL_ETHERNET
|
||||
config ETHERNET_UART_NAME
|
||||
string "ethernet uart name"
|
||||
default "/dev/uart3_dev3"
|
||||
|
|
|
@ -34,7 +34,7 @@ menu "stm32f407-st-discovery feature"
|
|||
endmenu
|
||||
|
||||
menu "config hardware resources for connection"
|
||||
if CONNECTION_COMMUNICATION_ETHERNET
|
||||
if CONNECTION_INDUSTRIAL_ETHERNET
|
||||
config ETHERNET_UART_NAME
|
||||
string "ethernet uart name"
|
||||
default "/dev/usart3_dev3"
|
||||
|
|
|
@ -33,7 +33,7 @@ menu "stm32f407zgt6 feature"
|
|||
endmenu
|
||||
|
||||
menu "config hardware resources for connection"
|
||||
if CONNECTION_COMMUNICATION_ETHERNET
|
||||
if CONNECTION_INDUSTRIAL_ETHERNET
|
||||
config ETHERNET_UART_NAME
|
||||
string "ethernet uart name"
|
||||
default "/dev/usart3_dev3"
|
||||
|
|
|
@ -77,6 +77,16 @@ $(if $(strip $(LOCALS)),$(eval $(LOCALS): $(1)
|
|||
@$(CROSS_COMPILE)gcc $$(AFLAGS) -c $$< -o $$@))
|
||||
endef
|
||||
|
||||
define add_a_file
|
||||
$(eval SOBJ := $(1:%.a=%.a)) \
|
||||
$(eval SOBJ := $(subst $(subst $(APP_DIR),,$(KERNEL_ROOT)),,$(SOBJ))) \
|
||||
$(eval LOCALA := $(addprefix $(BUILD_DIR)/,$(SOBJ))) \
|
||||
$(eval OBJS += $(LOCALA)) \
|
||||
$(if $(strip $(LOCALA)),$(eval $(LOCALA): $(1)
|
||||
@if [ ! -d $$(@D) ]; then mkdir -p $$(@D); fi
|
||||
@echo cp $$<
|
||||
@cp $$< $$@))
|
||||
endef
|
||||
|
||||
|
||||
|
||||
|
@ -92,7 +102,8 @@ $(if $(SRCS),$(foreach f,$(SRCS),$(call add_cc_file,$(addprefix $(CUR_DIR)/,$(f)
|
|||
SRCS := $(strip $(filter %.S,$(SRC_FILES)))
|
||||
$(if $(SRCS),$(foreach f,$(SRCS),$(call add_S_file,$(addprefix $(CUR_DIR)/,$(f)))))
|
||||
|
||||
|
||||
SRCS := $(strip $(filter %.a,$(SRC_FILES)))
|
||||
$(if $(SRCS),$(foreach f,$(SRCS),$(call add_a_file,$(addprefix $(CUR_DIR)/,$(f)))))
|
||||
|
||||
COMPILER:$(OBJS)
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
current_path=$(pwd)
|
||||
xizi_path=Ubiquitous/XiZi
|
||||
board=cortex-m3-emulator
|
||||
qemu_machine=lm3s6965evb
|
||||
board=cortex-m4-emulator
|
||||
qemu_machine=netduinoplus2
|
||||
|
||||
run_in_docker() {
|
||||
docker run \
|
||||
|
@ -31,11 +31,11 @@ distclean() {
|
|||
}
|
||||
|
||||
simulate() {
|
||||
[ "$1" = "debug" ] && debug_param="-s -S"
|
||||
qemu-system-arm $debug_param \
|
||||
-machine $qemu_machine \
|
||||
-nographic \
|
||||
-kernel $xizi_path/build/XiZi_$board.elf
|
||||
-kernel $xizi_path/build/XiZi_$board.elf \
|
||||
$@
|
||||
}
|
||||
|
||||
gdb() {
|
||||
|
|
Loading…
Reference in New Issue