Compare commits

...

25 Commits

Author SHA1 Message Date
Florian Pose b709e58147 Version bump to 1.6.9 2026-03-26 17:47:12 +01:00
Florian Pose 15883228f9 Merge branch 'fix-suse-16' into 'stable-1.6'
Driver fixes for openSUSE Leap 16.0

See merge request etherlab.org/ethercat!192
2026-03-26 17:45:44 +01:00
Florian Pose 9c63faf50d Fixed igb for SUSE kernel 6.12 2026-03-26 17:38:46 +01:00
Florian Pose bf706b737d Fixed genet for SUSE 16.0. 2026-03-26 17:26:45 +01:00
Florian Pose cf19168844 Cherry-picked MR 188 (injection-semaphore) from 1.7. 2026-03-26 16:41:43 +01:00
Florian Pose 98563a2f0d Merge branch 'no-config-necessary' into 'stable-1.6'
Do not require .config to exist in kernel sources

Closes #198

See merge request etherlab.org/ethercat!186
2026-03-24 17:13:53 +01:00
Florian Pose db526666f3 At least check for Makefile. 2026-03-24 17:07:12 +01:00
Florian Pose 1e61b8400c Minor: Improved comments in DC user example. 2026-03-24 17:05:00 +01:00
Florian Pose 6869c2bab8 Merge branch 'stable-1.6-kernel615' into 'stable-1.6'
tty: Implemented new timer interface since kernel 6.15.

See merge request etherlab.org/ethercat!187
2026-03-16 14:47:06 +01:00
Bernd Kuhls e32e99f8b8 tty: Implemented new timer interface since kernel 6.15.
Signed-off-by: Bernd Kuhls <bernd@kuhls.net>
2026-03-15 20:06:42 +01:00
Florian Pose 7a7d7f051b Merge branch 'calc-dc-after-attach' into 'stable-1.6'
Attach slaves before calculating DCs

Closes #212

See merge request etherlab.org/ethercat!185
2026-03-13 15:17:53 +01:00
Florian Pose 607d0fd1af Merge branch 'discard-eoe' into 'stable-1.6'
Discard EoE traffic if EoE is disabled

See merge request etherlab.org/ethercat!184
2026-03-13 15:16:29 +01:00
Florian Pose 212cb59d58 Do not require .config to exist in kernel sources. 2026-03-12 12:01:21 +01:00
Florian Pose c76b02ae2e Attach slaves before calculating DCs. 2026-03-12 11:36:37 +01:00
Florian Pose c8c23aa448 Discard EoE traffic in CoE statemachine, if EoE is disabled. 2026-03-10 09:24:13 +01:00
Florian Pose 4e5b661674 Merge branch 'fix-6.19' into 'stable-1.6'
Linux 6.19.0 support

Closes #200

See merge request etherlab.org/ethercat!183
2026-03-09 15:02:17 +01:00
Nicola Fontana c42c9cf8bc Linux 6.19.0 support
Commit 89aec171d9d1ab168e43fcf9754b82e4c0aef9b9 (part of linux kernel
6.19.0-rc1) introduced an arbitrarily sized sockaddr struct to be used
instead of the classical one.

Closes #200
2026-03-08 15:54:00 +01:00
Florian Pose 3ccae1d47d Updated NEWS.md 2026-03-03 08:56:21 +01:00
Florian Pose bde53bc4f3 Use /sbin/ip as default 2026-03-03 08:52:53 +01:00
Florian Pose f16c0ff3c3 Merge branch 'custom-paths' into 'stable-1.6'
Allow to customize kmod path and ip command

Closes #206

See merge request etherlab.org/ethercat!182
2026-03-03 08:51:06 +01:00
Nicola Fontana b86d2163f1 Fix #206: allow to customize utilities from configure
`ethercatctl` calls some utilites actually hardcoded in the script.
Provide a way to customize them from configure.

The default values are choosen to be backward compatible with the old
behavior, but more sensible values would be preferred, e.g.:

OPTION      ACTUAL DEFAULT      PREFERRED DEFAULT
kmod-dir    /sbin               $sbindir
ip-cmd      /bin/ip             $sbindir/ip

In a major future release this can be changed.
2026-03-02 12:09:59 +01:00
Nicola Fontana 90f9feb0ad Improve help string consistency
* Move default values from comments to help strings
* Use the "... [default=...]" convention everywhere
* Change "Enable ... driver" to more correct "Build ... driver"
* Fix --enable-dwmac-intel help string
* Fix --enable-fakeuserlib help string
* Change --disable-initd to --enable-initd to avoid confusion with
  `--disable-initd [default=yes]`.
2026-03-02 11:44:15 +01:00
Florian Pose 2543cc55bd Version 1.6.8: Fixed FAKE_EC_HOMEDIR usage. 2025-10-06 17:15:04 +02:00
Florian Pose 6acfd09764
Merge branch 'patch-1' into 'stable-1.6'
Set direction in syncManager when configuring it.

See merge request etherlab.org/ethercat!179
2025-09-09 11:08:42 +02:00
Jannik Becher c5413f81e2 Set direction in syncManager when configuring it.
This is needed when you configured your pdos without the ecrt_slave_config_pdos function.
2025-08-10 09:54:37 +00:00
15 changed files with 256 additions and 77 deletions

17
NEWS.md
View File

@ -1,3 +1,20 @@
# Version 1.6.9
- Protect datagram injection mechanism against re-ordering.
- Fixed for genet and igb drivers for openSUSE Leap 16.0 kernel 6.12.
- tty: Implemented new timer interface since kernel 6.15.
- Do not require .config to exist in kernel sources.
- Fix: Attach slaves before calculating DCs.
- Discard EoE traffic in CoE statemachine, if EoE is disabled.
- Support for Linux 6.19
- Added `--with-kmod-dir` and `--with-ip-cmd` configuration switches
to specify the paths of the tools used in the `ethercatctl` script.
- Changed the default path of the `ip` command to `/sbin/ip`.
# Version 1.6.8
- Fixed usage of `FAKE_EC_HOMEDIR` variable in fake library.
# Version 1.6.7 # Version 1.6.7
- Completed API methods in fake library - Completed API methods in fake library

View File

@ -28,7 +28,7 @@ AC_PREREQ([2.59])
# - Check for complete Doxygen comments # - Check for complete Doxygen comments
# - Update version number below # - Update version number below
# #
AC_INIT([ethercat], [1.6.7], [fp@igh.de]) AC_INIT([ethercat], [1.6.9], [fp@igh.de])
AC_CONFIG_AUX_DIR([autoconf]) AC_CONFIG_AUX_DIR([autoconf])
AM_INIT_AUTOMAKE([-Wall -Wno-override -Werror dist-bzip2 subdir-objects foreign]) AM_INIT_AUTOMAKE([-Wall -Wno-override -Werror dist-bzip2 subdir-objects foreign])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
@ -59,7 +59,7 @@ AC_MSG_CHECKING([whether to build kernel modules])
AC_ARG_ENABLE([kernel], AC_ARG_ENABLE([kernel],
AS_HELP_STRING([--enable-kernel], AS_HELP_STRING([--enable-kernel],
[Enable building kernel modules]), [Enable building kernel modules [default=yes]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) enablekernel=1 yes) enablekernel=1
@ -90,7 +90,7 @@ if test "x$enablekernel" = "x1"; then
AC_ARG_WITH([linux-dir], AC_ARG_WITH([linux-dir],
AS_HELP_STRING([--with-linux-dir=<DIR>], AS_HELP_STRING([--with-linux-dir=<DIR>],
[Linux kernel sources @<:@running kernel@:>@]), [Linux kernel sources [running kernel]]),
[ [
sourcedir=[$withval] sourcedir=[$withval]
], ],
@ -107,9 +107,9 @@ AC_ARG_WITH([linux-dir],
AC_MSG_CHECKING([for Linux kernel sources]) AC_MSG_CHECKING([for Linux kernel sources])
if test \! -r ${sourcedir}/.config; then if test \! -r ${sourcedir}/Makefile; then
echo echo
AC_MSG_ERROR([No configured Linux kernel sources in $sourcedir]) AC_MSG_ERROR([No Linux kernel sources in $sourcedir])
fi fi
# Try to get kernel release string # Try to get kernel release string
@ -127,7 +127,7 @@ fi
if test -z "$kernelrelease"; then if test -z "$kernelrelease"; then
echo echo
AC_MSG_ERROR([Failed to extract Linux kernel version!]) AC_MSG_ERROR([Failed to extract Linux kernel version! Does ${sourcedir} contain prepared kernel sources?])
fi fi
if test ${kernelrelease%%.*} -gt 2; then if test ${kernelrelease%%.*} -gt 2; then
@ -150,7 +150,7 @@ fi
AC_ARG_WITH([module-dir], AC_ARG_WITH([module-dir],
AS_HELP_STRING([--with-module-dir=<DIR>], AS_HELP_STRING([--with-module-dir=<DIR>],
[Linux module installation dir. Default: ethercat]), [Linux module installation dir [default=ethercat]]),
[moddir=[$withval]], [moddir=[$withval]],
[moddir="ethercat"] [moddir="ethercat"]
) )
@ -167,7 +167,7 @@ AC_MSG_CHECKING([whether to verify native driver resources])
AC_ARG_ENABLE([driver-resource-verifying], AC_ARG_ENABLE([driver-resource-verifying],
AS_HELP_STRING([--enable-driver-resource-verifying], AS_HELP_STRING([--enable-driver-resource-verifying],
[Verify resource (de-)allocation in native drivers]), [Verify resource (de-)allocation in native drivers [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) enableverifying=1 yes) enableverifying=1
@ -196,7 +196,7 @@ AC_SUBST(ENABLE_DRIVER_RESOURCE_VERIFYING, [$enableverifying])
AC_ARG_ENABLE([generic], AC_ARG_ENABLE([generic],
AS_HELP_STRING([--enable-generic], AS_HELP_STRING([--enable-generic],
[Enable generic Ethernet driver]), [Build generic Ethernet driver [default=enable-kernel]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) enablegeneric=1 yes) enablegeneric=1
@ -219,7 +219,7 @@ AC_SUBST(ENABLE_GENERIC, [$enablegeneric])
AC_ARG_ENABLE([8139too], AC_ARG_ENABLE([8139too],
AS_HELP_STRING([--enable-8139too], AS_HELP_STRING([--enable-8139too],
[Enable 8139too driver]), [Build 8139too driver [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) enable8139too=1 yes) enable8139too=1
@ -230,7 +230,7 @@ AC_ARG_ENABLE([8139too],
;; ;;
esac esac
], ],
[enable8139too=0] # disabled by default [enable8139too=0]
) )
AM_CONDITIONAL(ENABLE_8139TOO, test "x$enable8139too" = "x1") AM_CONDITIONAL(ENABLE_8139TOO, test "x$enable8139too" = "x1")
@ -272,7 +272,7 @@ AC_SUBST(KERNEL_8139TOO, [$kernel8139too])
AC_ARG_ENABLE([e100], AC_ARG_ENABLE([e100],
AS_HELP_STRING([--enable-e100], AS_HELP_STRING([--enable-e100],
[Enable e100 driver]), [Build e100 driver [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) enablee100=1 yes) enablee100=1
@ -283,7 +283,7 @@ AC_ARG_ENABLE([e100],
;; ;;
esac esac
], ],
[enablee100=0] # disabled by default [enablee100=0]
) )
AM_CONDITIONAL(ENABLE_E100, test "x$enablee100" = "x1") AM_CONDITIONAL(ENABLE_E100, test "x$enablee100" = "x1")
@ -325,7 +325,7 @@ AC_SUBST(KERNEL_E100, [$kernele100])
AC_ARG_ENABLE([e1000], AC_ARG_ENABLE([e1000],
AS_HELP_STRING([--enable-e1000], AS_HELP_STRING([--enable-e1000],
[Enable e1000 driver]), [Build e1000 driver [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) enablee1000=1 yes) enablee1000=1
@ -336,7 +336,7 @@ AC_ARG_ENABLE([e1000],
;; ;;
esac esac
], ],
[enablee1000=0] # disabled by default [enablee1000=0]
) )
AM_CONDITIONAL(ENABLE_E1000, test "x$enablee1000" = "x1") AM_CONDITIONAL(ENABLE_E1000, test "x$enablee1000" = "x1")
@ -378,7 +378,7 @@ AC_SUBST(KERNEL_E1000, [$kernele1000])
AC_ARG_ENABLE([e1000e], AC_ARG_ENABLE([e1000e],
AS_HELP_STRING([--enable-e1000e], AS_HELP_STRING([--enable-e1000e],
[Enable e1000e driver]), [Build e1000e driver [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) enablee1000e=1 yes) enablee1000e=1
@ -389,7 +389,7 @@ AC_ARG_ENABLE([e1000e],
;; ;;
esac esac
], ],
[enablee1000e=0] # disabled by default [enablee1000e=0]
) )
AM_CONDITIONAL(ENABLE_E1000E, test "x$enablee1000e" = "x1") AM_CONDITIONAL(ENABLE_E1000E, test "x$enablee1000e" = "x1")
@ -451,7 +451,7 @@ AC_SUBST(E1000E_LAYOUT, [$e1000elayout])
AC_ARG_ENABLE([genet], AC_ARG_ENABLE([genet],
AS_HELP_STRING([--enable-genet], AS_HELP_STRING([--enable-genet],
[Enable genet driver (for Raspi 4)]), [Build genet driver for Raspi 4 [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) enablegenet=1 yes) enablegenet=1
@ -462,7 +462,7 @@ AC_ARG_ENABLE([genet],
;; ;;
esac esac
], ],
[enablegenet=0] # disabled by default [enablegenet=0]
) )
AM_CONDITIONAL(ENABLE_GENET, test "x$enablegenet" = "x1") AM_CONDITIONAL(ENABLE_GENET, test "x$enablegenet" = "x1")
@ -497,7 +497,7 @@ AC_SUBST(KERNEL_GENET, [$kernelgenet])
AC_ARG_ENABLE([igb], AC_ARG_ENABLE([igb],
AS_HELP_STRING([--enable-igb], AS_HELP_STRING([--enable-igb],
[Enable igb driver]), [Build igb driver [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) enableigb=1 yes) enableigb=1
@ -508,7 +508,7 @@ AC_ARG_ENABLE([igb],
;; ;;
esac esac
], ],
[enableigb=0] # disabled by default [enableigb=0]
) )
AM_CONDITIONAL(ENABLE_IGB, test "x$enableigb" = "x1") AM_CONDITIONAL(ENABLE_IGB, test "x$enableigb" = "x1")
@ -544,7 +544,7 @@ AC_SUBST(KERNEL_IGB, [$kerneligb])
AC_ARG_ENABLE([igc], AC_ARG_ENABLE([igc],
AS_HELP_STRING([--enable-igc], AS_HELP_STRING([--enable-igc],
[Enable igc driver]), [Build igc driver [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) enableigc=1 yes) enableigc=1
@ -555,7 +555,7 @@ AC_ARG_ENABLE([igc],
;; ;;
esac esac
], ],
[enableigc=0] # disabled by default [enableigc=0]
) )
AM_CONDITIONAL(ENABLE_IGC, test "x$enableigc" = "x1") AM_CONDITIONAL(ENABLE_IGC, test "x$enableigc" = "x1")
@ -606,7 +606,7 @@ has_r8169_leds=0
AC_ARG_ENABLE([r8169], AC_ARG_ENABLE([r8169],
AS_HELP_STRING([--enable-r8169], AS_HELP_STRING([--enable-r8169],
[Enable r8169 driver]), [Build r8169 driver [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) enable_r8169=1 yes) enable_r8169=1
@ -617,7 +617,7 @@ AC_ARG_ENABLE([r8169],
;; ;;
esac esac
], ],
[enable_r8169=0] # disabled by default [enable_r8169=0]
) )
AM_CONDITIONAL(ENABLE_R8169, test "x$enable_r8169" = "x1") AM_CONDITIONAL(ENABLE_R8169, test "x$enable_r8169" = "x1")
@ -681,7 +681,7 @@ enablestmmac=0
AC_ARG_ENABLE([stmmac-pci], AC_ARG_ENABLE([stmmac-pci],
AS_HELP_STRING([--enable-stmmac-pci], AS_HELP_STRING([--enable-stmmac-pci],
[Enable stmmac driver]), [Build stmmac driver [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) enablestmmacpci=1 yes) enablestmmacpci=1
@ -693,7 +693,7 @@ AC_ARG_ENABLE([stmmac-pci],
;; ;;
esac esac
], ],
[enablestmmacpci=0] # disabled by default [enablestmmacpci=0]
) )
AM_CONDITIONAL(ENABLE_STMMACPCI, test "x$enablestmmacpci" = "x1") AM_CONDITIONAL(ENABLE_STMMACPCI, test "x$enablestmmacpci" = "x1")
@ -701,7 +701,7 @@ AC_SUBST(ENABLE_STMMACPCI, [$enablestmmacpci])
AC_ARG_ENABLE([dwmac-intel], AC_ARG_ENABLE([dwmac-intel],
AS_HELP_STRING([--enable-dwmac-intel], AS_HELP_STRING([--enable-dwmac-intel],
[Enable stmmac driver]), [Build dwmac intel driver [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) enabledwmacintel=1 yes) enabledwmacintel=1
@ -713,7 +713,7 @@ AC_ARG_ENABLE([dwmac-intel],
;; ;;
esac esac
], ],
[enabledwmacintel=0] # disabled by default [enabledwmacintel=0]
) )
AM_CONDITIONAL(ENABLE_DWMACINTEL, test "x$enabledwmacintel" = "x1") AM_CONDITIONAL(ENABLE_DWMACINTEL, test "x$enabledwmacintel" = "x1")
@ -764,7 +764,7 @@ AC_MSG_CHECKING([whether to build the CCAT driver])
AC_ARG_ENABLE([ccat], AC_ARG_ENABLE([ccat],
AS_HELP_STRING([--enable-ccat], AS_HELP_STRING([--enable-ccat],
[Enable CCAT driver]), [Build CCAT driver [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) enableccat=1 yes) enableccat=1
@ -775,7 +775,7 @@ AC_ARG_ENABLE([ccat],
;; ;;
esac esac
], ],
[enableccat=0] # disabled by default [enableccat=0]
) )
if test "x${enableccat}" = "x1"; then if test "x${enableccat}" = "x1"; then
@ -848,7 +848,7 @@ AC_ARG_WITH([xenomai-dir],
AC_ARG_WITH([xenomai-config], AC_ARG_WITH([xenomai-config],
AS_HELP_STRING([--with-xenomai-config=<CMD>], AS_HELP_STRING([--with-xenomai-config=<CMD>],
[Xenomai config invokation, default to xenomai-dir/bin/xeno-config]), [Xenomai config invocation [default=xenomai-dir/bin/xeno-config]]),
[ [
xenomaiconfig=[$withval] xenomaiconfig=[$withval]
], ],
@ -946,7 +946,7 @@ AC_MSG_CHECKING([whether to build the debug interface])
AC_ARG_ENABLE([debug-if], AC_ARG_ENABLE([debug-if],
AS_HELP_STRING([--enable-debug-if], AS_HELP_STRING([--enable-debug-if],
[Create a debug interface for each master @<:@NO@:>@]), [Create a debug interface for each master [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) dbg=1 yes) dbg=1
@ -978,7 +978,7 @@ AC_MSG_CHECKING([whether to build the debug ring])
AC_ARG_ENABLE([debug-ring], AC_ARG_ENABLE([debug-ring],
AS_HELP_STRING([--enable-debug-ring], AS_HELP_STRING([--enable-debug-ring],
[Create a debug ring to record frames @<:@NO@:>@]), [Create a debug ring to record frames [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) debugring=1 yes) debugring=1
@ -1007,7 +1007,7 @@ AC_MSG_CHECKING([whether to build with EoE support])
AC_ARG_ENABLE([eoe], AC_ARG_ENABLE([eoe],
AS_HELP_STRING([--enable-eoe], AS_HELP_STRING([--enable-eoe],
[Enable EoE support (default: yes)]), [Enable EoE support [default=yes]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) eoe=1 yes) eoe=1
@ -1039,7 +1039,7 @@ AC_MSG_CHECKING([whether to use the CPU timestamp counter])
AC_ARG_ENABLE([cycles], AC_ARG_ENABLE([cycles],
AS_HELP_STRING([--enable-cycles], AS_HELP_STRING([--enable-cycles],
[Use CPU timestamp counter (default: no)]), [Use CPU timestamp counter [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) cycles=1 yes) cycles=1
@ -1068,7 +1068,7 @@ AC_MSG_CHECKING([whether to use high-resolution timers for scheduling])
AC_ARG_ENABLE([hrtimer], AC_ARG_ENABLE([hrtimer],
AS_HELP_STRING([--enable-hrtimer], AS_HELP_STRING([--enable-hrtimer],
[Use high-resolution timer for scheduling (default: no)]), [Use high-resolution timer for scheduling [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) hrtimer=1 yes) hrtimer=1
@ -1097,7 +1097,7 @@ AC_MSG_CHECKING([whether to read alias addresses from registers])
AC_ARG_ENABLE([regalias], AC_ARG_ENABLE([regalias],
AS_HELP_STRING([--enable-regalias], AS_HELP_STRING([--enable-regalias],
[Read alias adresses from register (default: no)]), [Read alias adresses from register [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) regalias=1 yes) regalias=1
@ -1126,7 +1126,7 @@ AC_MSG_CHECKING([whether to build the command-line tool])
AC_ARG_ENABLE([tool], AC_ARG_ENABLE([tool],
AS_HELP_STRING([--enable-tool], AS_HELP_STRING([--enable-tool],
[Build command-line tool (default: yes)]), [Build command-line tool [default=yes]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) tool=1 yes) tool=1
@ -1156,7 +1156,7 @@ AC_MSG_CHECKING([whether to build the userspace library])
AC_ARG_ENABLE([userlib], AC_ARG_ENABLE([userlib],
AS_HELP_STRING([--enable-userlib], AS_HELP_STRING([--enable-userlib],
[Generation of the userspace library (default: yes)]), [Generation of userspace library [default=yes]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) userlib=1 yes) userlib=1
@ -1186,7 +1186,7 @@ AC_MSG_CHECKING([whether to build the fake userspace library])
AC_ARG_ENABLE([fakeuserlib], AC_ARG_ENABLE([fakeuserlib],
AS_HELP_STRING([--enable-fakeuserlib], AS_HELP_STRING([--enable-fakeuserlib],
[Generation of the userspace library (default: no)]), [Generation of fake userspace library [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) fakeuserlib=1 yes) fakeuserlib=1
@ -1217,7 +1217,7 @@ AC_MSG_CHECKING([whether to build the tty driver])
AC_ARG_ENABLE([tty], AC_ARG_ENABLE([tty],
AS_HELP_STRING([--enable-tty], AS_HELP_STRING([--enable-tty],
[Generation of the ec_tty module (default: no)]), [Generation of the ec_tty module [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) tty=1 yes) tty=1
@ -1248,7 +1248,7 @@ AC_MSG_CHECKING([whether to allow identification wildcards])
AC_ARG_ENABLE([wildcards], AC_ARG_ENABLE([wildcards],
AS_HELP_STRING([--enable-wildcards], AS_HELP_STRING([--enable-wildcards],
[Enable vendor ID / product code wildcards (default: no)]), [Enable vendor ID / product code wildcards [default=no]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) wildcards=1 yes) wildcards=1
@ -1276,7 +1276,7 @@ fi
AC_ARG_WITH([devices], AC_ARG_WITH([devices],
AS_HELP_STRING([--with-devices=<NUMBER>], AS_HELP_STRING([--with-devices=<NUMBER>],
[Number of Ethernet devices per master. Default: 1]), [Number of Ethernet devices per master [default=1]]),
[ [
devices=[$withval] devices=[$withval]
], ],
@ -1308,7 +1308,7 @@ AC_MSG_CHECKING([whether to assign the SII to PDI])
AC_ARG_ENABLE([sii-assign], AC_ARG_ENABLE([sii-assign],
AS_HELP_STRING([--enable-sii-assign], AS_HELP_STRING([--enable-sii-assign],
[Enable SII assignment to PDI (default: yes)]), [Enable SII assignment to PDI [default=yes]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) siiassign=1 yes) siiassign=1
@ -1337,7 +1337,7 @@ AC_MSG_CHECKING([whether to syslog in realtime context])
AC_ARG_ENABLE([rt-syslog], AC_ARG_ENABLE([rt-syslog],
AS_HELP_STRING([--enable-rt-syslog], AS_HELP_STRING([--enable-rt-syslog],
[Enable RT syslog (default: yes)]), [Enable RT syslog [default=yes]]),
[ [
case "${enableval}" in case "${enableval}" in
yes) rtsyslog=1 yes) rtsyslog=1
@ -1363,8 +1363,8 @@ fi
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
AC_ARG_ENABLE([initd], AC_ARG_ENABLE([initd],
AS_HELP_STRING([--disable-initd], AS_HELP_STRING([--enable-initd],
[Disable /etc/init.d script support (default: enabled)]) [Install /etc/init.d scripts [default=yes]])
) )
AM_CONDITIONAL(HAVE_INITD, test "x$enable_initd" != "xno") AM_CONDITIONAL(HAVE_INITD, test "x$enable_initd" != "xno")
@ -1397,6 +1397,32 @@ esac
AM_CONDITIONAL(HAVE_SYSTEMD, test "x$with_systemdsystemunitdir" != "x") AM_CONDITIONAL(HAVE_SYSTEMD, test "x$with_systemdsystemunitdir" != "x")
AC_SUBST(systemdsystemunitdir, [$with_systemdsystemunitdir]) AC_SUBST(systemdsystemunitdir, [$with_systemdsystemunitdir])
#-----------------------------------------------------------------------------
# System utilities
#-----------------------------------------------------------------------------
AC_ARG_WITH([kmod-dir],
AS_HELP_STRING([--with-kmod-dir=<DIR>],
[Path to kernel module utilities [default=/sbin]]),
[kmoddir=[$withval]],
[kmoddir="/sbin"]
)
AC_MSG_CHECKING([for path to kernel modules])
AC_MSG_RESULT([$kmoddir])
AC_SUBST(kmoddir, [$kmoddir])
AC_ARG_WITH([ip-cmd],
AS_HELP_STRING([--with-ip-cmd=<CMD>],
['ip' command to use [default=/sbin/ip]]),
[ipcmd=[$withval]],
[ipcmd="/sbin/ip"]
)
AC_MSG_CHECKING([for ip command])
AC_MSG_RESULT([$ipcmd])
AC_SUBST(ipcmd, [$ipcmd])
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
AC_CONFIG_FILES([ AC_CONFIG_FILES([

View File

@ -234,7 +234,11 @@ int ec_gen_device_create_socket(
sa.sll_family = AF_PACKET; sa.sll_family = AF_PACKET;
sa.sll_protocol = htons(ETH_P_ETHERCAT); sa.sll_protocol = htons(ETH_P_ETHERCAT);
sa.sll_ifindex = desc->ifindex; sa.sll_ifindex = desc->ifindex;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 19, 0)
ret = kernel_bind(dev->socket, (struct sockaddr_unsized *) &sa, sizeof(sa));
#else
ret = kernel_bind(dev->socket, (struct sockaddr *) &sa, sizeof(sa)); ret = kernel_bind(dev->socket, (struct sockaddr *) &sa, sizeof(sa));
#endif
if (ret) { if (ret) {
printk(KERN_ERR PFX "Failed to bind() socket to interface" printk(KERN_ERR PFX "Failed to bind() socket to interface"
" (ret = %i).\n", ret); " (ret = %i).\n", ret);

View File

@ -2459,7 +2459,11 @@ static int bcmgenet_rx_poll(struct napi_struct *napi, int budget)
if (ring->dim.use_dim) { if (ring->dim.use_dim) {
dim_update_sample(ring->dim.event_ctr, ring->dim.packets, dim_update_sample(ring->dim.event_ctr, ring->dim.packets,
ring->dim.bytes, &dim_sample); ring->dim.bytes, &dim_sample);
#ifdef CONFIG_SUSE_KERNEL
net_dim(&ring->dim.dim, &dim_sample);
#else
net_dim(&ring->dim.dim, dim_sample); net_dim(&ring->dim.dim, dim_sample);
#endif
} }
return work_done; return work_done;

View File

@ -2513,6 +2513,9 @@ static int igb_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
struct net_device *dev, struct net_device *dev,
const unsigned char *addr, u16 vid, const unsigned char *addr, u16 vid,
u16 flags, u16 flags,
#ifdef CONFIG_SUSE_KERNEL
bool *notified,
#endif
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
/* guarantee we can provide a unique filter for the unicast address */ /* guarantee we can provide a unique filter for the unicast address */

View File

@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
* *
* Copyright (C) 2007-2022 Florian Pose, Ingenieurgemeinschaft IgH * Copyright (C) 2007-2026 Florian Pose, Ingenieurgemeinschaft IgH
* *
* This file is part of the IgH EtherCAT Master. * This file is part of the IgH EtherCAT Master.
* *
@ -300,8 +300,14 @@ int main(int argc, char **argv)
if (off_counter_out < 0) if (off_counter_out < 0)
return -1; return -1;
// configure SYNC signals for this slave // configure SYNC0/SYNC1 interrupts for this slave
ecrt_slave_config_dc(sc, 0x0700, PERIOD_NS, 4400000, 0, 0); ecrt_slave_config_dc(sc,
0x0700, // AssignActivate (see vendor docs)
PERIOD_NS, // SYNC0 cycle time [ns]
4400000, // SYNC0 shift time [ns]
0, // SYNC1 cycle time [ns]
0 // SYNC1 shift time [ns]
);
printf("Activating master...\n"); printf("Activating master...\n");
if (ecrt_master_activate(master)) if (ecrt_master_activate(master))

View File

@ -233,7 +233,11 @@ static void __exit cleanup_mini_module(void)
{ {
printk(KERN_INFO PFX "Stopping...\n"); printk(KERN_INFO PFX "Stopping...\n");
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
timer_delete_sync(&timer);
#else
del_timer_sync(&timer); del_timer_sync(&timer);
#endif
free_serial_devices(); free_serial_devices();

View File

@ -9,14 +9,16 @@ data level by running two applications back to back.
## Supported features ## Supported features
Currently, only a very limited subset of libethercat functionality is Although the library implements the complete API (to avoid undefined
supported: references), most function calls will just do nothing and return no error.
However, some methods have a bit of logic implemented to simulate a working
master. This is what is possible:
- Creating master and domain instances - Creating master and domain instances
- Activating master, `send`/`receive`. - Activating master, `send()` and `receive()`.
- Processing and queuing domains - Processing and queuing domains
- Configuring PDOs - Configuring PDOs
- Configuring SDOs using `ecrt_slave_config_sdo*` - Configuring SDOs using `ecrt_slave_config_sdo*()`
The SDO config does not do anything, but when activating the master the SDO The SDO config does not do anything, but when activating the master the SDO
config will be dumped into a JSON file. config will be dumped into a JSON file.

View File

@ -573,11 +573,11 @@ static int mkpath(const std::string &file_path)
static std::string getRtIpcDir(int idx) static std::string getRtIpcDir(int idx)
{ {
std::string ans; std::string ans("/tmp/FakeEtherCAT");
if (const auto e = getenv("FAKE_EC_HOMEDIR")) { if (const auto e = getenv("FAKE_EC_HOMEDIR")) {
ans = e + std::string("/") + std::to_string(idx); ans = e;
} }
ans = "/tmp/FakeEtherCAT/" + std::to_string(idx); ans += std::string("/") + std::to_string(idx);
mkpath(ans); mkpath(ans);
return ans; return ans;
} }
@ -617,6 +617,9 @@ int ecrt_slave_config_sync_manager(
ec_watchdog_mode_t watchdog_mode /** Watchdog mode. */ ec_watchdog_mode_t watchdog_mode /** Watchdog mode. */
) )
{ {
auto &syncManager = sc->sync_managers[sync_index];
syncManager.dir = direction;
return 0; return 0;
} }

View File

@ -539,6 +539,16 @@ void ec_fsm_coe_dict_response(
return; return;
} }
#ifndef EC_EOE
if (mbox_prot == EC_MBOX_TYPE_EOE) {
// discard EoE message and wait for the next reponse
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_coe_dict_check;
return;
}
#endif
if (mbox_prot != EC_MBOX_TYPE_COE) { if (mbox_prot != EC_MBOX_TYPE_COE) {
EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n", EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
mbox_prot); mbox_prot);
@ -821,6 +831,16 @@ void ec_fsm_coe_dict_desc_response(
return; return;
} }
#ifndef EC_EOE
if (mbox_prot == EC_MBOX_TYPE_EOE) {
// discard EoE message and wait for the next reponse
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_coe_dict_desc_check;
return;
}
#endif
if (mbox_prot != EC_MBOX_TYPE_COE) { if (mbox_prot != EC_MBOX_TYPE_COE) {
EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n", EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
mbox_prot); mbox_prot);
@ -1057,6 +1077,16 @@ void ec_fsm_coe_dict_entry_response(
return; return;
} }
#ifndef EC_EOE
if (mbox_prot == EC_MBOX_TYPE_EOE) {
// discard EoE message and wait for the next reponse
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_coe_dict_entry_check;
return;
}
#endif
if (mbox_prot != EC_MBOX_TYPE_COE) { if (mbox_prot != EC_MBOX_TYPE_COE) {
EC_SLAVE_ERR(slave, "Received mailbox protocol" EC_SLAVE_ERR(slave, "Received mailbox protocol"
" 0x%02X as response.\n", mbox_prot); " 0x%02X as response.\n", mbox_prot);
@ -1574,6 +1604,16 @@ void ec_fsm_coe_down_response(
return; return;
} }
#ifndef EC_EOE
if (mbox_prot == EC_MBOX_TYPE_EOE) {
// discard EoE message and wait for the next reponse
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_coe_down_check;
return;
}
#endif
if (mbox_prot != EC_MBOX_TYPE_COE) { if (mbox_prot != EC_MBOX_TYPE_COE) {
request->errno = EIO; request->errno = EIO;
fsm->state = ec_fsm_coe_error; fsm->state = ec_fsm_coe_error;
@ -1752,6 +1792,16 @@ void ec_fsm_coe_down_seg_response(
return; return;
} }
#ifndef EC_EOE
if (mbox_prot == EC_MBOX_TYPE_EOE) {
// discard EoE message and wait for the next reponse
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_coe_down_check;
return;
}
#endif
if (mbox_prot != EC_MBOX_TYPE_COE) { if (mbox_prot != EC_MBOX_TYPE_COE) {
request->errno = EIO; request->errno = EIO;
fsm->state = ec_fsm_coe_error; fsm->state = ec_fsm_coe_error;
@ -2114,10 +2164,15 @@ void ec_fsm_coe_up_response(
return; return;
} }
if (master->debug_level) { #ifndef EC_EOE
EC_SLAVE_DBG(slave, 1, "Upload response:\n"); if (mbox_prot == EC_MBOX_TYPE_EOE) {
ec_print_data(data, rec_size); // discard EoE message and wait for the next reponse
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_coe_up_check;
return;
} }
#endif
if (mbox_prot != EC_MBOX_TYPE_COE) { if (mbox_prot != EC_MBOX_TYPE_COE) {
request->errno = EIO; request->errno = EIO;
@ -2135,6 +2190,11 @@ void ec_fsm_coe_up_response(
return; return;
} }
if (master->debug_level) {
EC_SLAVE_DBG(slave, 1, "Upload response:\n");
ec_print_data(data, rec_size);
}
if (rec_size < 6) { if (rec_size < 6) {
request->errno = EIO; request->errno = EIO;
fsm->state = ec_fsm_coe_error; fsm->state = ec_fsm_coe_error;
@ -2411,10 +2471,15 @@ void ec_fsm_coe_up_seg_response(
return; return;
} }
if (master->debug_level) { #ifndef EC_EOE
EC_SLAVE_DBG(slave, 1, "Upload segment response:\n"); if (mbox_prot == EC_MBOX_TYPE_EOE) {
ec_print_data(data, rec_size); // discard EoE message and wait for the next reponse
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_coe_up_seg_check;
return;
} }
#endif
if (mbox_prot != EC_MBOX_TYPE_COE) { if (mbox_prot != EC_MBOX_TYPE_COE) {
EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n", EC_SLAVE_ERR(slave, "Received mailbox protocol 0x%02X as response.\n",
@ -2432,6 +2497,12 @@ void ec_fsm_coe_up_seg_response(
return; return;
} }
if (master->debug_level) {
EC_SLAVE_DBG(slave, 1, "Upload segment response:\n");
ec_print_data(data, rec_size);
}
if (rec_size < 10) { if (rec_size < 10) {
EC_SLAVE_ERR(slave, "Received currupted SDO upload" EC_SLAVE_ERR(slave, "Received currupted SDO upload"
" segment response!\n"); " segment response!\n");

View File

@ -989,11 +989,12 @@ void ec_fsm_master_state_scan_slave(
master->scan_index = master->slave_count; master->scan_index = master->slave_count;
wake_up_interruptible(&master->scan_queue); wake_up_interruptible(&master->scan_queue);
ec_master_calc_dc(master);
// Attach slave configurations // Attach slave configurations
ec_master_attach_slave_configs(master); ec_master_attach_slave_configs(master);
// Calculate DC (needs attached slaves due to reference clock selection)
ec_master_calc_dc(master);
#ifdef EC_EOE #ifdef EC_EOE
// check if EoE processing has to be started // check if EoE processing has to be started
ec_master_eoe_start(master); ec_master_eoe_start(master);

View File

@ -61,6 +61,23 @@
rt_mutex_lock_interruptible(lock, 0) rt_mutex_lock_interruptible(lock, 0)
#endif #endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 47)
#define smp_store_release(p, v) \
do { \
smp_mb(); \
ACCESS_ONCE(*p) = (v); \
} while (0)
#define smp_load_acquire(p) \
({ \
typeof(*p) ___p1 = ACCESS_ONCE(*p); \
smp_mb(); \
___p1; \
})
#endif
#include "master.h" #include "master.h"
/****************************************************************************/ /****************************************************************************/
@ -195,6 +212,7 @@ int ec_master_init(ec_master_t *master, /**< EtherCAT master */
master->phase = EC_ORPHANED; master->phase = EC_ORPHANED;
master->active = 0; master->active = 0;
master->config_changed = 0; master->config_changed = 0;
master->injection_seq_fsm = 0; master->injection_seq_fsm = 0;
master->injection_seq_rt = 0; master->injection_seq_rt = 0;
@ -1596,6 +1614,7 @@ static int ec_master_idle_thread(void *priv_data)
static int ec_master_operation_thread(void *priv_data) static int ec_master_operation_thread(void *priv_data)
{ {
ec_master_t *master = (ec_master_t *) priv_data; ec_master_t *master = (ec_master_t *) priv_data;
unsigned int seq_rt;
EC_MASTER_DBG(master, 1, "Operation thread running" EC_MASTER_DBG(master, 1, "Operation thread running"
" with fsm interval = %u us, max data size=%zu\n", " with fsm interval = %u us, max data size=%zu\n",
@ -1604,7 +1623,11 @@ static int ec_master_operation_thread(void *priv_data)
while (!kthread_should_stop()) { while (!kthread_should_stop()) {
ec_datagram_output_stats(&master->fsm_datagram); ec_datagram_output_stats(&master->fsm_datagram);
if (master->injection_seq_rt == master->injection_seq_fsm) { /* Use smp_load_acquire() to prevent re-ordering.
* https://gitlab.com/etherlab.org/ethercat/-/work_items/168 */
seq_rt = smp_load_acquire(&master->injection_seq_rt);
if (seq_rt == master->injection_seq_fsm) { // was injected
// output statistics // output statistics
ec_master_output_stats(master); ec_master_output_stats(master);
@ -1616,7 +1639,9 @@ static int ec_master_operation_thread(void *priv_data)
if (ec_fsm_master_exec(&master->fsm)) { if (ec_fsm_master_exec(&master->fsm)) {
// Inject datagrams (let the RT thread queue them, see // Inject datagrams (let the RT thread queue them, see
// ecrt_master_send()) // ecrt_master_send())
master->injection_seq_fsm++; // re-ordering-safe version of `master->injection_seq_fsm++`
smp_store_release(&master->injection_seq_fsm,
master->injection_seq_fsm + 1);
} }
ec_master_exec_slave_fsms(master); ec_master_exec_slave_fsms(master);
@ -2436,11 +2461,14 @@ int ecrt_master_send(ec_master_t *master)
{ {
ec_datagram_t *datagram, *n; ec_datagram_t *datagram, *n;
ec_device_index_t dev_idx; ec_device_index_t dev_idx;
unsigned int seq_fsm;
if (master->injection_seq_rt != master->injection_seq_fsm) { seq_fsm = smp_load_acquire(&master->injection_seq_fsm);
if (master->injection_seq_rt != seq_fsm) {
// inject datagram produced by master FSM // inject datagram produced by master FSM
ec_master_queue_datagram(master, &master->fsm_datagram); ec_master_queue_datagram(master, &master->fsm_datagram);
master->injection_seq_rt = master->injection_seq_fsm;
smp_store_release(&master->injection_seq_rt, seq_fsm);
} }
ec_master_inject_external_datagrams(master); ec_master_inject_external_datagrams(master);

View File

@ -68,6 +68,8 @@ endif
# Any precious variable used inside script_templates should appear here # Any precious variable used inside script_templates should appear here
expand_script = $(SED) \ expand_script = $(SED) \
-e 's,[@]VERSION[@],$(VERSION),g' \ -e 's,[@]VERSION[@],$(VERSION),g' \
-e 's,[@]ipcmd[@],$(ipcmd),g' \
-e 's,[@]kmoddir[@],$(kmoddir),g' \
-e 's,[@]bindir[@],$(bindir),g' \ -e 's,[@]bindir[@],$(bindir),g' \
-e 's,[@]sbindir[@],$(sbindir),g' \ -e 's,[@]sbindir[@],$(sbindir),g' \
-e 's,[@]sysconfdir[@],$(sysconfdir),g' -e 's,[@]sysconfdir[@],$(sysconfdir),g'

View File

@ -25,13 +25,13 @@
# #
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
LSMOD=/sbin/lsmod LSMOD="@kmoddir@/lsmod"
MODPROBE=/sbin/modprobe MODPROBE="@kmoddir@/modprobe"
RMMOD=/sbin/rmmod RMMOD="@kmoddir@/rmmod"
MODINFO=/sbin/modinfo MODINFO="@kmoddir@/modinfo"
IP=/bin/ip IP="@ipcmd@"
ETHERCAT=@bindir@/ethercat ETHERCAT="@bindir@/ethercat"
#------------------------------------------------------------------------------ #------------------------------------------------------------------------------
@ -39,7 +39,7 @@ if [ "$1" = "-c" ]; then
ETHERCAT_CONFIG="$2" ETHERCAT_CONFIG="$2"
COMMAND="$3" COMMAND="$3"
else else
ETHERCAT_CONFIG=@sysconfdir@/ethercat.conf ETHERCAT_CONFIG="@sysconfdir@/ethercat.conf"
COMMAND="$1" COMMAND="$1"
fi fi

View File

@ -292,7 +292,11 @@ static int ec_tty_init(ec_tty_t *t, int minor,
static void ec_tty_clear(ec_tty_t *tty) static void ec_tty_clear(ec_tty_t *tty)
{ {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
timer_delete_sync(&tty->timer);
#else
del_timer_sync(&tty->timer); del_timer_sync(&tty->timer);
#endif
tty_unregister_device(tty_driver, tty->minor); tty_unregister_device(tty_driver, tty->minor);
} }
@ -367,10 +371,14 @@ static void ec_tty_wakeup(struct timer_list *t)
static void ec_tty_wakeup(unsigned long data) static void ec_tty_wakeup(unsigned long data)
#endif #endif
{ {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 15, 0)
ec_tty_t *tty = timer_container_of(tty, t, timer);
#else
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
ec_tty_t *tty = from_timer(tty, t, timer); ec_tty_t *tty = from_timer(tty, t, timer);
#else #else
ec_tty_t *tty = (ec_tty_t *) data; ec_tty_t *tty = (ec_tty_t *) data;
#endif
#endif #endif
size_t to_recv; size_t to_recv;