powerlink: build liboplkmn.a and liboplkcn.a

This commit is contained in:
Jiacheng Shi 2022-03-26 13:51:38 +08:00
parent 7e1307a3bb
commit b7648f0f08
30 changed files with 3436 additions and 14 deletions

View File

@ -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

View File

@ -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)

View File

@ -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"))

View File

@ -0,0 +1,3 @@
*
.*
!.gitignore

View File

@ -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()

View File

@ -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

View File

@ -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>

View File

@ -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 .)

View File

@ -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_

View File

@ -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 .)

View File

@ -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_

View File

@ -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
/// \{
/// \}

View File

@ -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
/// \{
/// \}

View File

@ -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, &currentTime) != 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
/// \{
/// \}

View File

@ -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;
}

View File

@ -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);
}
/// \}

View File

@ -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
/// \}

View File

@ -846,6 +846,8 @@ static tOplkError downloadCycleLength(tCfmNodeInfo* pNodeInfo_p)
pNodeInfo_p->eventCnProgress.nodeId,
ret);
}
#else
UNUSED_PARAMETER(pNodeInfo_p);
#endif
return ret;

View File

@ -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);
}
/// \}

View File

@ -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,

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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)

View File

@ -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() {