# HG changeset patch # User Florian Pose # Date 1147246898 0 # Node ID 342ad851ec786dd4102802141aad832815c30d54 # Parent 7572c5bf7bb332beef2da29f1be804a4b6cd51b3 Added examples directory. diff -r 7572c5bf7bb3 -r 342ad851ec78 examples/mini/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/mini/Makefile Wed May 10 07:41:38 2006 +0000 @@ -0,0 +1,60 @@ +#---------------------------------------------------------------- +# +# Makefile +# +# Minimal EtherCAT module. +# +# $Id$ +# +# Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH +# +# This file is part of the IgH EtherCAT Master. +# +# The IgH EtherCAT Master is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; version 2 of the License. +# +# The IgH EtherCAT Master is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with the IgH EtherCAT Master; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +#---------------------------------------------------------------- + +ifneq ($(KERNELRELEASE),) + +#---------------------------------------------------------------- +# kbuild section +#---------------------------------------------------------------- + +obj-m := ec_mini.o + +ec_mini-objs := mini.o + +#---------------------------------------------------------------- + +else + +#---------------------------------------------------------------- +# default section +#---------------------------------------------------------------- + +ifneq ($(wildcard ethercat.conf),) +include ethercat.conf +else +KERNELDIR = /usr/src/linux +endif + +modules: + $(MAKE) -C $(KERNELDIR) M=`pwd` + +clean: + $(MAKE) -C $(KERNELDIR) M=`pwd` clean + +#---------------------------------------------------------------- + +endif diff -r 7572c5bf7bb3 -r 342ad851ec78 examples/mini/ethercat.conf.tmpl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/mini/ethercat.conf.tmpl Wed May 10 07:41:38 2006 +0000 @@ -0,0 +1,13 @@ +#------------------------------------------------------------------------------ +# +# EtherCAT Konfigurationsdatei Kernel 2.6 +# +# $Id$ +# +# This file is a versioned template configuration. Copy it to "ethercat.conf" +# (which is ignored by Subversion) and adjust it to your needs. +# +#------------------------------------------------------------------------------ + +KERNELDIR = /usr/src/linux + diff -r 7572c5bf7bb3 -r 342ad851ec78 examples/mini/mini.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/mini/mini.c Wed May 10 07:41:38 2006 +0000 @@ -0,0 +1,255 @@ +/****************************************************************************** + * + * m i n i . c + * + * Minimal module for EtherCAT. + * + * $Id$ + * + * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 of the License. + * + * The IgH EtherCAT Master is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#include +#include +#include +#include +#include + +#include "../include/ecrt.h" // EtherCAT realtime interface + +#define ASYNC +#define FREQUENCY 100 + +/*****************************************************************************/ + +struct timer_list timer; + +// EtherCAT +ec_master_t *master = NULL; +ec_domain_t *domain1 = NULL; +spinlock_t master_lock = SPIN_LOCK_UNLOCKED; + +// data fields +//void *r_ssi_input, *r_ssi_status, *r_4102[3]; + +// channels +uint32_t k_pos; +uint8_t k_stat; + +ec_field_init_t domain1_fields[] = { + {NULL, "3", "Beckhoff", "EL5001", "InputValue", 0}, + {NULL, "2", "Beckhoff", "EL4132", "OutputValue", 0}, + {} +}; + +/*****************************************************************************/ + +void run(unsigned long data) +{ + static unsigned int counter = 0; + + spin_lock(&master_lock); + +#ifdef ASYNC + // receive + ecrt_master_async_receive(master); + ecrt_domain_process(domain1); +#else + // send and receive + ecrt_domain_queue(domain1); + ecrt_master_run(master); + ecrt_master_sync_io(master); + ecrt_domain_process(domain1); +#endif + + // process data + //k_pos = EC_READ_U32(r_ssi); + +#ifdef ASYNC + // send + ecrt_domain_queue(domain1); + ecrt_master_run(master); + ecrt_master_async_send(master); +#endif + + spin_unlock(&master_lock); + + if (counter) { + counter--; + } + else { + counter = FREQUENCY; + //printk(KERN_INFO "k_pos = %i\n", k_pos); + //printk(KERN_INFO "k_stat = 0x%02X\n", k_stat); + } + + // restart timer + timer.expires += HZ / FREQUENCY; + add_timer(&timer); +} + +/*****************************************************************************/ + +int request_lock(void *data) +{ + unsigned int tries = 0; + while (1) { + if (spin_trylock(&master_lock)) { + if (tries) printk(KERN_INFO "lock: %i tries needed.\n", tries); + return 1; + } + tries++; + } +} + +/*****************************************************************************/ + +void release_lock(void *data) +{ + spin_unlock(&master_lock); +} + +/*****************************************************************************/ + +int __init init_mini_module(void) +{ + printk(KERN_INFO "=== Starting Minimal EtherCAT environment... ===\n"); + + if ((master = ecrt_request_master(0)) == NULL) { + printk(KERN_ERR "Requesting master 0 failed!\n"); + goto out_return; + } + + ecrt_master_callbacks(master, request_lock, release_lock, NULL); + + printk(KERN_INFO "Registering domain...\n"); + if (!(domain1 = ecrt_master_create_domain(master))) + { + printk(KERN_ERR "Domain creation failed!\n"); + goto out_release_master; + } + + printk(KERN_INFO "Registering domain fields...\n"); + if (ecrt_domain_register_field_list(domain1, domain1_fields)) { + printk(KERN_ERR "Field registration failed!\n"); + goto out_release_master; + } + + printk(KERN_INFO "Activating master...\n"); + if (ecrt_master_activate(master)) { + printk(KERN_ERR "Failed to activate master!\n"); + goto out_release_master; + } + +#if 0 + if (ecrt_master_fetch_sdo_lists(master)) { + printk(KERN_ERR "Failed to fetch SDO lists!\n"); + goto out_deactivate; + } + ecrt_master_print(master, 2); +#else + ecrt_master_print(master, 0); +#endif + +#if 0 + if (!(slave = ecrt_master_get_slave(master, "5"))) { + printk(KERN_ERR "Failed to get slave 5!\n"); + goto out_deactivate; + } + + if (ecrt_slave_sdo_write_exp8(slave, 0x4061, 1, 0) || + ecrt_slave_sdo_write_exp8(slave, 0x4061, 2, 1) || + ecrt_slave_sdo_write_exp8(slave, 0x4061, 3, 1) || + ecrt_slave_sdo_write_exp8(slave, 0x4066, 0, 0) || + ecrt_slave_sdo_write_exp8(slave, 0x4067, 0, 4) || + ecrt_slave_sdo_write_exp8(slave, 0x4068, 0, 0) || + ecrt_slave_sdo_write_exp8(slave, 0x4069, 0, 25) || + ecrt_slave_sdo_write_exp8(slave, 0x406A, 0, 25) || + ecrt_slave_sdo_write_exp8(slave, 0x406B, 0, 50)) { + printk(KERN_ERR "Failed to configure SSI slave!\n"); + goto out_deactivate; + } +#endif + +#if 0 + printk(KERN_INFO "Writing alias...\n"); + if (ecrt_slave_sdo_write_exp16(slave, 0xBEEF)) { + printk(KERN_ERR "Failed to write alias!\n"); + goto out_deactivate; + } +#endif + +#ifdef ASYNC + // send once and wait... + ecrt_master_prepare_async_io(master); +#endif + +#if 1 + if (ecrt_master_start_eoe(master)) { + printk(KERN_ERR "Failed to start EoE processing!\n"); + goto out_deactivate; + } +#endif + + printk("Starting cyclic sample thread.\n"); + init_timer(&timer); + timer.function = run; + timer.expires = jiffies + 10; + add_timer(&timer); + + printk(KERN_INFO "=== Minimal EtherCAT environment started. ===\n"); + return 0; + +#if 1 + out_deactivate: + ecrt_master_deactivate(master); +#endif + out_release_master: + ecrt_release_master(master); + out_return: + return -1; +} + +/*****************************************************************************/ + +void __exit cleanup_mini_module(void) +{ + printk(KERN_INFO "=== Stopping Minimal EtherCAT environment... ===\n"); + + if (master) { + del_timer_sync(&timer); + printk(KERN_INFO "Deactivating master...\n"); + ecrt_master_deactivate(master); + ecrt_release_master(master); + } + + printk(KERN_INFO "=== Minimal EtherCAT environment stopped. ===\n"); +} + +/*****************************************************************************/ + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR ("Florian Pose "); +MODULE_DESCRIPTION ("EtherCAT minimal test environment"); + +module_init(init_mini_module); +module_exit(cleanup_mini_module); + +/*****************************************************************************/ + diff -r 7572c5bf7bb3 -r 342ad851ec78 examples/rt/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/rt/Makefile Wed May 10 07:41:38 2006 +0000 @@ -0,0 +1,87 @@ +#------------------------------------------------------------------------------ +# +# Makefile +# +# $Id$ +# +# Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH +# +# This file is part of the IgH EtherCAT Master. +# +# The IgH EtherCAT Master is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; version 2 of the License. +# +# The IgH EtherCAT Master is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with the IgH EtherCAT Master; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +#------------------------------------------------------------------------------ + +ifneq ($(KERNELRELEASE),) + +#------------------------------------------------------------------------------ +# kbuild section +#------------------------------------------------------------------------------ + +ifneq ($(wildcard $(src)/rt.conf),) +include $(src)/rt.conf +else +MODULENAME := rt +endif + +obj-m := $(MODULENAME).o + +$(MODULENAME)-objs := msr_rt.o \ + rt_lib/msr-core/msr_lists.o \ + rt_lib/msr-core/msr_main.o \ + rt_lib/msr-core/msr_charbuf.o \ + rt_lib/msr-core/msr_reg.o \ + rt_lib/msr-core/msr_interpreter.o \ + rt_lib/msr-core/msr_messages.o \ + rt_lib/msr-core/msr_proc.o \ + rt_lib/msr-core/msr_error_reg.o \ + rt_lib/msr-utils/msr_utils.o \ + rt_lib/msr-utils/msr_time.o \ + rt_lib/msr-math/msr_base64.o \ + rt_lib/msr-math/msr_hex_bin.o \ + libm.o + +EXTRA_CFLAGS := -I$(src)/rt_lib/msr-include -D_SIMULATION \ + -I/usr/include -mhard-float \ + -DSVNREV=$(shell svnversion $(src)) -DUSER=$(USER) + +#------------------------------------------------------------------------------ + +else + +#------------------------------------------------------------------------------ +# default section +#------------------------------------------------------------------------------ + +ifneq ($(wildcard rt.conf),) +include rt.conf +else +MODULENAME := msr_rt +KERNEL := $(shell uname -r) +endif + +KERNELDIR := /lib/modules/$(KERNEL)/build + +modules: + $(MAKE) -C $(KERNELDIR) M=`pwd` + +clean: + $(MAKE) -C $(KERNELDIR) M=`pwd` clean + +install: + @./install.sh $(MODULENAME) $(KERNEL) + +#------------------------------------------------------------------------------ + +endif diff -r 7572c5bf7bb3 -r 342ad851ec78 examples/rt/install.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/rt/install.sh Wed May 10 07:41:38 2006 +0000 @@ -0,0 +1,66 @@ +#!/bin/sh + +#------------------------------------------------------------------------------ +# +# Realtime module install script +# +# $Id: install.sh 5 2006-04-07 13:49:10Z fp $ +# +# Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH +# +# This file is part of the IgH EtherCAT Master. +# +# The IgH EtherCAT Master is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; version 2 of the License. +# +# The IgH EtherCAT Master is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with the IgH EtherCAT Master; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +#------------------------------------------------------------------------------ + +# Fetch parameters + +if [ $# -ne 2 ]; then + echo "Usage: $0 " + exit 1 +fi + +MODULENAME=$1 +KERNEL=$2 + +MODULESDIR=/lib/modules/$KERNEL/kernel/drivers/rt + +echo "Realtime installer" +echo " target: $MODULENAME" +echo " kernel: $KERNEL" + +# Create target directory + +if [ ! -d $MODULESDIR ]; then + echo " creating $MODULESDIR..." + mkdir $MODULESDIR || exit 1 +fi + +# Install files + +echo " installing $MODULENAME..." +if ! cp $MODULENAME.ko $MODULESDIR/$MODULENAME.ko; then exit 1; fi + +# Calculate dependencies + +echo " building module dependencies..." +depmod + +# Finish + +echo "done." +exit 0 + +#------------------------------------------------------------------------------ diff -r 7572c5bf7bb3 -r 342ad851ec78 examples/rt/libm.o_shipped --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/rt/libm.o_shipped Wed May 10 07:41:38 2006 +0000 @@ -0,0 +1,1 @@ +/usr/lib/libm.a \ No newline at end of file diff -r 7572c5bf7bb3 -r 342ad851ec78 examples/rt/msr_load --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/rt/msr_load Wed May 10 07:41:38 2006 +0000 @@ -0,0 +1,36 @@ +#!/bin/sh +module="msr_rt" +device="msr" +mode="664" + +# Group: since distributions do it differently, look for wheel or use staff +if grep '^staff:' /etc/group > /dev/null; then + group="staff" +else + group="wheel" +fi + +# invoke insmod with all arguments we got +# and use a pathname, as newer modutils don't look in . by default +/sbin/insmod -f ./$module.ko $* || exit 1 + +major=`cat /proc/devices | awk "\\$2==\"$device\" {print \\$1}"` + +echo $major +# Remove stale nodes and replace them, then give gid and perms +# Usually the script is shorter, it's scull that has several devices in it. + +rm -f /dev/${device} +mknod /dev/${device} c $major 0 +# ln -sf ${device}0 /dev/${device} +chgrp users /dev/${device} +chmod $mode /dev/${device} + + + + + + + + + diff -r 7572c5bf7bb3 -r 342ad851ec78 examples/rt/msr_param.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/rt/msr_param.h Wed May 10 07:41:38 2006 +0000 @@ -0,0 +1,31 @@ +/****************************************************************************** + * + * $Id$ + * + * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 of the License. + * + * The IgH EtherCAT Master is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +#ifndef _MSR_PARAM_H_ +#define _MSR_PARAM_H_ + +#define MSR_ABTASTFREQUENZ 1000 + +#endif + +/*****************************************************************************/ diff -r 7572c5bf7bb3 -r 342ad851ec78 examples/rt/msr_rt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/rt/msr_rt.c Wed May 10 07:41:38 2006 +0000 @@ -0,0 +1,296 @@ +/****************************************************************************** + * + * m s r _ r t . c + * + * Kernelmodul für 2.6 Kernel zur Meßdatenerfassung, Steuerung und Regelung. + * + * $Id$ + * + * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; version 2 of the License. + * + * The IgH EtherCAT Master is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + *****************************************************************************/ + +// Linux +#include +#include +#include +#include +#include + +// RT_lib +#include +#include +#include +#include +#include +#include +#include "msr_param.h" + +// EtherCAT +#include "../include/ecrt.h" + +#define ASYNC + +// Defines/Makros +#define HZREDUCTION (MSR_ABTASTFREQUENZ / HZ) + +/*****************************************************************************/ +/* Globale Variablen */ + +// Adeos +static struct ipipe_domain this_domain; +static struct ipipe_sysinfo sys_info; + +// EtherCAT +ec_master_t *master = NULL; +ec_domain_t *domain1 = NULL; + +// Prozessdaten +void *r_ssi; +void *r_ssi_st; + +// KanŽäle +uint32_t k_ssi; +uint32_t k_ssi_st; + +ec_field_init_t domain1_fields[] = { + {&r_ssi, "0:3", "Beckhoff", "EL5001", "InputValue", 0}, + {&r_ssi_st, "0:3", "Beckhoff", "EL5001", "Status", 0}, + {} +}; + +/*****************************************************************************/ + +static void msr_controller_run(void) +{ +#ifdef ASYNC + // Empfangen + ecrt_master_async_receive(master); + ecrt_domain_process(domain1); +#else + // Senden und empfangen + ecrt_domain_queue(domain1); + ecrt_master_run(master); + ecrt_master_sync_io(master); + ecrt_domain_process(domain1); +#endif + + // Prozessdaten verarbeiten + k_ssi = EC_READ_U32(r_ssi); + k_ssi_st = EC_READ_U8 (r_ssi_st); + +#ifdef ASYNC + // Senden + ecrt_domain_queue(domain1); + ecrt_master_run(master); + ecrt_master_async_send(master); +#endif +} + +/*****************************************************************************/ + +int msr_globals_register(void) +{ + msr_reg_kanal("/ssi_position", "", &k_ssi, TUINT); + msr_reg_kanal("/ssi_status", "", &k_ssi_st, TUINT); + return 0; +} + +/*****************************************************************************/ + +void msr_run(unsigned irq) +{ + static int counter = 0; + + MSR_ADEOS_INTERRUPT_CODE(msr_controller_run(); msr_write_kanal_list();); + + ipipe_control_irq(irq, 0, IPIPE_ENABLE_MASK); // Interrupt bestŽätigen + if (++counter >= HZREDUCTION) { + ipipe_propagate_irq(irq); // und weiterreichen + counter = 0; + } +} + +/*****************************************************************************/ + +void domain_entry(void) +{ + printk("Domain %s started.\n", ipipe_current_domain->name); + + ipipe_get_sysinfo(&sys_info); + ipipe_virtualize_irq(ipipe_current_domain,sys_info.archdep.tmirq, + &msr_run, NULL, IPIPE_HANDLE_MASK); + + ipipe_tune_timer(1000000000UL / MSR_ABTASTFREQUENZ, 0); +} + +/*****************************************************************************/ + +int __init init_rt_module(void) +{ + struct ipipe_domain_attr attr; //ipipe +#if 1 + ec_slave_t *slave; +#endif + + // Als allererstes die RT-Lib initialisieren + if (msr_rtlib_init(1, MSR_ABTASTFREQUENZ, 10, &msr_globals_register) < 0) { + printk(KERN_ERR "Failed to initialize rtlib!\n"); + goto out_return; + } + + if ((master = ecrt_request_master(0)) == NULL) { + printk(KERN_ERR "Failed to request master 0!\n"); + goto out_msr_cleanup; + } + + //ecrt_master_print(master, 2); + + printk(KERN_INFO "Creating domains...\n"); + if (!(domain1 = ecrt_master_create_domain(master))) { + printk(KERN_ERR "Failed to create domains!\n"); + goto out_release_master; + } + + printk(KERN_INFO "Registering domain fields...\n"); + if (ecrt_domain_register_field_list(domain1, domain1_fields)) { + printk(KERN_ERR "Failed to register domain fields.\n"); + goto out_release_master; + } + + printk(KERN_INFO "Activating master...\n"); + if (ecrt_master_activate(master)) { + printk(KERN_ERR "Could not activate master!\n"); + goto out_release_master; + } + +#if 0 + if (ecrt_master_start_eoe(master)) { + printk(KERN_ERR "Failed to start EoE processing!\n"); + goto out_deactivate; + } +#endif + +#if 0 + if (ecrt_master_fetch_sdo_lists(master)) { + printk(KERN_ERR "Failed to fetch SDO lists!\n"); + goto out_deactivate; + } + ecrt_master_print(master, 2); +#else + ecrt_master_print(master, 0); +#endif + +#if 1 + if (!(slave = ecrt_master_get_slave(master, "0:3"))) { + printk(KERN_ERR "Failed to get slave!\n"); + goto out_deactivate; + } + + if ( + ecrt_slave_sdo_write_exp8(slave, 0x4061, 1, 1) || // disable frame error bit + ecrt_slave_sdo_write_exp8(slave, 0x4061, 2, 0) || // power failure bit + ecrt_slave_sdo_write_exp8(slave, 0x4061, 3, 1) || // inhibit time + ecrt_slave_sdo_write_exp8(slave, 0x4061, 4, 0) || // test mode + ecrt_slave_sdo_write_exp8(slave, 0x4066, 0, 1) || // dualcode + ecrt_slave_sdo_write_exp8(slave, 0x4067, 0, 5) || // 125kbaud + ecrt_slave_sdo_write_exp8(slave, 0x4068, 0, 0) || // single-turn + ecrt_slave_sdo_write_exp8(slave, 0x4069, 0, 25) || // frame size + ecrt_slave_sdo_write_exp8(slave, 0x406A, 0, 25) || // data length + ecrt_slave_sdo_write_exp16(slave, 0x406B, 0, 30000) // inhibit time in us + ) { + printk(KERN_ERR "Failed to configure SSI slave!\n"); + goto out_deactivate; + } +#endif + +#if 0 + if (!(slave = ecrt_master_get_slave(master, "1:0"))) { + printk(KERN_ERR "Failed to get slave!\n"); + goto out_deactivate; + } + if (ecrt_slave_write_alias(slave, 0x5678)) { + printk(KERN_ERR "Failed to write alias!\n"); + goto out_deactivate; + } +#endif + +#ifdef ASYNC + // Einmal senden und warten... + ecrt_master_prepare_async_io(master); +#endif + + ipipe_init_attr(&attr); + attr.name = "IPIPE-MSR-MODULE"; + attr.priority = IPIPE_ROOT_PRIO + 1; + attr.entry = &domain_entry; + ipipe_register_domain(&this_domain, &attr); + return 0; + +#if 1 + out_deactivate: + ecrt_master_deactivate(master); +#endif + out_release_master: + ecrt_release_master(master); + out_msr_cleanup: + msr_rtlib_cleanup(); + out_return: + return -1; +} + +/*****************************************************************************/ + +void __exit cleanup_rt_module(void) +{ + printk(KERN_INFO "Cleanign up rt module...\n"); + + ipipe_tune_timer(1000000000UL / HZ, 0); // Alten Timertakt wiederherstellen + ipipe_unregister_domain(&this_domain); + + printk(KERN_INFO "=== Stopping EtherCAT environment... ===\n"); + ecrt_master_deactivate(master); + ecrt_release_master(master); + printk(KERN_INFO "=== EtherCAT environment stopped. ===\n"); + + msr_rtlib_cleanup(); +} + +/*****************************************************************************/ + +#define EC_LIT(X) #X +#define EC_STR(X) EC_LIT(X) +#define COMPILE_INFO "Revision " EC_STR(SVNREV) \ + ", compiled by " EC_STR(USER) \ + " at " __DATE__ " " __TIME__ + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR ("Florian Pose "); +MODULE_DESCRIPTION ("EtherCAT real-time test environment"); +MODULE_VERSION(COMPILE_INFO); + +module_init(init_rt_module); +module_exit(cleanup_rt_module); + +/*****************************************************************************/ + +/* Emacs-Konfiguration +;;; Local Variables: *** +;;; c-basic-offset:4 *** +;;; End: *** +*/ diff -r 7572c5bf7bb3 -r 342ad851ec78 examples/rt/msr_unload --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/rt/msr_unload Wed May 10 07:41:38 2006 +0000 @@ -0,0 +1,9 @@ +#!/bin/sh +module="msr_rt" +device="msr" + +# invoke rmmod with all arguments we got +/sbin/rmmod $module $* || exit 1 + +# Remove stale nodes +rm -f /dev/${device} /dev/${device}0 diff -r 7572c5bf7bb3 -r 342ad851ec78 examples/rt/msrserv.pl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/rt/msrserv.pl Wed May 10 07:41:38 2006 +0000 @@ -0,0 +1,257 @@ +#!/usr/bin/perl -w + +#------------------------------------------------------------------------------ +# +# Copyright (C) 2006 Ingenieurgemeinschaft IgH +# +# This file is part of the IgH EtherCAT Master. +# +# The IgH EtherCAT Master is free software; you can redistribute it +# and/or modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; version 2 of the License. +# +# The IgH EtherCAT Master is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with the IgH EtherCAT Master; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# +#------------------------------------------------------------------------------ +# +# Multithreaded Server +# according to the example from "Programming Perl" +# this code is improved according to the example from +# perldoc perlipc, so now safely being usable under Perl 5.8 +# (see note (*)) +# +# works with read/write on a device-file +# +#------------------------------------------------------------------------------ + +require 5.002; +use strict; +BEGIN { $ENV{PATH} = '/opt/msr/bin:/usr/bin:/bin' } +use Socket; +use Carp; +use FileHandle; +use Getopt::Std; + +use Sys::Syslog qw(:DEFAULT setlogsock); + +use vars qw ( + $self $pid $dolog $port $dev %opts $selfbase + $len $offset $stream $written $read $log $blksize + $instdir + $authfile %authhosts + ); + + +# Do logging to local syslogd by unix-domain socket instead of inetd +setlogsock("unix"); + +# Prototypes and some little Tools +sub spawn; +sub logmsg { + my ($level, $debug, @text) = @_; + syslog("daemon|$level", @text) if $debug > $dolog; +# print STDERR "daemon|$level", @text, "\n" if $dolog; +} +sub out { + my $waitpid = wait; + logmsg("notice", 2, "$waitpid exited"); + unlink "$selfbase.pid"; + exit 0; +} + +sub help { + print "\n usage: $0 [-l og] [-h elp] [-p port] [-d device]\n"; + exit; +} + +# Process Options +%opts = ( + "l" => 1, + "h" => 0, + "p" => 2345, + "d" => "/dev/msr" + ); + +getopts("lhp:d:", \%opts); + +help if $opts{"h"}; + +( $self = $0 ) =~ s+.*/++ ; +( $selfbase = $self ) =~ s/\..*//; +$log = "$selfbase.log"; +$dolog = $opts{"l"}; +$port = $opts{"p"}; +$dev = $opts{"d"}; +$blksize = 1024; # try to write as much bytes +$instdir = "/opt/msr"; +$authfile = "$instdir/etc/hosts.auth"; + +# Start logging +openlog($self, 'pid'); + +# Flush Output, dont buffer +$| = 1; + +# first fork and run in background +if ($pid = fork) { +# open LOG, ">$log" if $dolog; +# close LOG; + logmsg("notice", 2, "forked process: $pid\n"); + exit 0; +} + +# Server tells about startup success +open (PID, ">/$instdir/var/run/$selfbase.pid"); +print PID "$$\n"; +close PID; + +# Cleanup on exit (due to kill -TERM signal) +$SIG{TERM} = \&out; + +# We use streams +my $proto = getprotobyname('tcp'); + +# Open Server socket +socket(Server, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; +setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) + or die "setsocketopt: $!"; +bind (Server, sockaddr_in($port, INADDR_ANY)) + or die "bind: $!"; +listen (Server, SOMAXCONN) + or die "listen: $!"; + +%authhosts = (); +# get authorized hosts +open (AUTH, $authfile) + or logmsg ("notice", 2, "Could not read allowed hosts file: $authfile"); +while () { + chomp; + my $host = lc $_; + if ($host =~ /^[\d\w]/) { + $authhosts{$_} = 1; + logmsg ("notice", 2, "Authorized host: >$host<"); + } +} +close (AUTH); + +# tell about open server socket +logmsg ("notice", 2, "Server started at port $port"); + +my $waitedpid = 0; +my $paddr; + +# wait for children to return, thus avoiding zombies +# improvement (*) +use POSIX ":sys_wait_h"; +sub REAPER { + my $child; + while (($waitedpid = waitpid(-1,WNOHANG)) > 0) { + logmsg ("notice", 2, "reaped $waitedpid", ($? ? " with exit $?" : "")); + } + $SIG{CHLD} = \&REAPER; # loathe sysV +} + +# also all sub-processes should wait for their children +$SIG{CHLD} = \&REAPER; + +# start a new server for every incoming request +# improvement (*) -- loop forever + +while ( 1 ) { + for ( $waitedpid = 0; + ($paddr = accept(Client,Server)) || $waitedpid; + $waitedpid = 0, close Client ) { + next if $waitedpid and not $paddr; + my ($port, $iaddr) = sockaddr_in($paddr); + my $name = lc gethostbyaddr($iaddr, AF_INET); + my $ipaddr = inet_ntoa($iaddr); + my $n = 0; + +# tell about the requesting client + logmsg ("info", 2, "Connection from >$ipaddr< ($name) at port $port"); + + spawn sub { + my ($head, $hlen, $pos, $pegel, $typ, $siz, $nch, $nrec, $dat, $i, $j, $n, $llen); + my ($watchpegel, $shmpegel); + my ($rin, $rout, $in, $line, $data_requested, $oversample); + my (@channels); + +# to use stdio on writing to Client + Client->autoflush(); + +# Open Device + sysopen (DEV, "$dev", O_RDWR | O_NONBLOCK, 0666) or die("can't open $dev"); + +# Bitmask to check for input on stdin + $rin = ""; + vec($rin, fileno(Client), 1) = 1; + +# check for authorized hosts + my $access = 'deny'; + $access = 'allow' if $authhosts{$ipaddr}; + $line = "\n"; + logmsg ("info", 2, $line); + $len = length $line; + $offset = 0; + while ($len) { + $written = syswrite (DEV, $line, $len, $offset); + $len -= $written; + $offset += $written; + } + + while ( 1 ) { + $in = select ($rout=$rin, undef, undef, 0.0); # poll client +# look for any Input from Client + if ($in) { +# exit on EOF + $len = sysread (Client, $line, $blksize) or exit; + logmsg("info", 0, "got $len bytes: \"$line\""); + $offset = 0; +# copy request to device + while ($len) { + $written = syswrite (DEV, $line, $len, $offset); + $len -= $written; + $offset += $written; + } + } +# look for some output from device + if ($len = sysread DEV, $stream, $blksize) { + print Client $stream; + } else { + select undef, undef, undef, 0.1; # calm down if nothing on device + } + } + }; + logmsg("info", 2, "spawned\n"); + } + logmsg("info", 2, "server loop\n"); +} + +sub spawn { + my $coderef = shift; + + unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') { + confess "usage: spawn CODEREF"; + } + my $pid; + if (!defined($pid = fork)) { + logmsg ("notice", 2, "fork failed: $!"); + return; + } elsif ($pid) { + logmsg ("notice", 2, "Request $pid"); + return; # Parent + } + +# do not use fdup as in the original example +# open (STDIN, "<&Client") or die "Can't dup client to stdin"; +# open (STDOUT, ">&Client") or die "Can't dup client to stdout"; +# STDOUT->autoflush(); + exit &$coderef(); +} diff -r 7572c5bf7bb3 -r 342ad851ec78 examples/rt/rt.conf.tmpl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/examples/rt/rt.conf.tmpl Wed May 10 07:41:38 2006 +0000 @@ -0,0 +1,18 @@ +#------------------------------------------------------------------------------ +# +# Configuration file for msr realtime modules +# +# $Id$ +# +# This file is a versioned template configuration. Copy it to "rt.conf" +# (which is ignored by Subversion) and adjust it to your needs. +# +#------------------------------------------------------------------------------ + +# Module name (without extension) +MODULENAME := ec_rt_sample + +# The kernel to compile the EtherCAT sources against +KERNEL := `uname -r` + +#------------------------------------------------------------------------------ diff -r 7572c5bf7bb3 -r 342ad851ec78 mini/Makefile --- a/mini/Makefile Tue May 09 10:13:53 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -#---------------------------------------------------------------- -# -# Makefile -# -# Minimal EtherCAT module. -# -# $Id$ -# -# Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH -# -# This file is part of the IgH EtherCAT Master. -# -# The IgH EtherCAT Master is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; version 2 of the License. -# -# The IgH EtherCAT Master is distributed in the hope that it will be -# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with the IgH EtherCAT Master; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# -#---------------------------------------------------------------- - -ifneq ($(KERNELRELEASE),) - -#---------------------------------------------------------------- -# kbuild section -#---------------------------------------------------------------- - -obj-m := ec_mini.o - -ec_mini-objs := mini.o - -#---------------------------------------------------------------- - -else - -#---------------------------------------------------------------- -# default section -#---------------------------------------------------------------- - -ifneq ($(wildcard ethercat.conf),) -include ethercat.conf -else -KERNELDIR = /usr/src/linux -endif - -modules: - $(MAKE) -C $(KERNELDIR) M=`pwd` - -clean: - $(MAKE) -C $(KERNELDIR) M=`pwd` clean - -#---------------------------------------------------------------- - -endif diff -r 7572c5bf7bb3 -r 342ad851ec78 mini/ethercat.conf.tmpl --- a/mini/ethercat.conf.tmpl Tue May 09 10:13:53 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -#------------------------------------------------------------------------------ -# -# EtherCAT Konfigurationsdatei Kernel 2.6 -# -# $Id$ -# -# This file is a versioned template configuration. Copy it to "ethercat.conf" -# (which is ignored by Subversion) and adjust it to your needs. -# -#------------------------------------------------------------------------------ - -KERNELDIR = /usr/src/linux - diff -r 7572c5bf7bb3 -r 342ad851ec78 mini/mini.c --- a/mini/mini.c Tue May 09 10:13:53 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,255 +0,0 @@ -/****************************************************************************** - * - * m i n i . c - * - * Minimal module for EtherCAT. - * - * $Id$ - * - * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it - * and/or modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; version 2 of the License. - * - * The IgH EtherCAT Master is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - -#include -#include -#include -#include -#include - -#include "../include/ecrt.h" // EtherCAT realtime interface - -#define ASYNC -#define FREQUENCY 100 - -/*****************************************************************************/ - -struct timer_list timer; - -// EtherCAT -ec_master_t *master = NULL; -ec_domain_t *domain1 = NULL; -spinlock_t master_lock = SPIN_LOCK_UNLOCKED; - -// data fields -//void *r_ssi_input, *r_ssi_status, *r_4102[3]; - -// channels -uint32_t k_pos; -uint8_t k_stat; - -ec_field_init_t domain1_fields[] = { - {NULL, "3", "Beckhoff", "EL5001", "InputValue", 0}, - {NULL, "2", "Beckhoff", "EL4132", "OutputValue", 0}, - {} -}; - -/*****************************************************************************/ - -void run(unsigned long data) -{ - static unsigned int counter = 0; - - spin_lock(&master_lock); - -#ifdef ASYNC - // receive - ecrt_master_async_receive(master); - ecrt_domain_process(domain1); -#else - // send and receive - ecrt_domain_queue(domain1); - ecrt_master_run(master); - ecrt_master_sync_io(master); - ecrt_domain_process(domain1); -#endif - - // process data - //k_pos = EC_READ_U32(r_ssi); - -#ifdef ASYNC - // send - ecrt_domain_queue(domain1); - ecrt_master_run(master); - ecrt_master_async_send(master); -#endif - - spin_unlock(&master_lock); - - if (counter) { - counter--; - } - else { - counter = FREQUENCY; - //printk(KERN_INFO "k_pos = %i\n", k_pos); - //printk(KERN_INFO "k_stat = 0x%02X\n", k_stat); - } - - // restart timer - timer.expires += HZ / FREQUENCY; - add_timer(&timer); -} - -/*****************************************************************************/ - -int request_lock(void *data) -{ - unsigned int tries = 0; - while (1) { - if (spin_trylock(&master_lock)) { - if (tries) printk(KERN_INFO "lock: %i tries needed.\n", tries); - return 1; - } - tries++; - } -} - -/*****************************************************************************/ - -void release_lock(void *data) -{ - spin_unlock(&master_lock); -} - -/*****************************************************************************/ - -int __init init_mini_module(void) -{ - printk(KERN_INFO "=== Starting Minimal EtherCAT environment... ===\n"); - - if ((master = ecrt_request_master(0)) == NULL) { - printk(KERN_ERR "Requesting master 0 failed!\n"); - goto out_return; - } - - ecrt_master_callbacks(master, request_lock, release_lock, NULL); - - printk(KERN_INFO "Registering domain...\n"); - if (!(domain1 = ecrt_master_create_domain(master))) - { - printk(KERN_ERR "Domain creation failed!\n"); - goto out_release_master; - } - - printk(KERN_INFO "Registering domain fields...\n"); - if (ecrt_domain_register_field_list(domain1, domain1_fields)) { - printk(KERN_ERR "Field registration failed!\n"); - goto out_release_master; - } - - printk(KERN_INFO "Activating master...\n"); - if (ecrt_master_activate(master)) { - printk(KERN_ERR "Failed to activate master!\n"); - goto out_release_master; - } - -#if 0 - if (ecrt_master_fetch_sdo_lists(master)) { - printk(KERN_ERR "Failed to fetch SDO lists!\n"); - goto out_deactivate; - } - ecrt_master_print(master, 2); -#else - ecrt_master_print(master, 0); -#endif - -#if 0 - if (!(slave = ecrt_master_get_slave(master, "5"))) { - printk(KERN_ERR "Failed to get slave 5!\n"); - goto out_deactivate; - } - - if (ecrt_slave_sdo_write_exp8(slave, 0x4061, 1, 0) || - ecrt_slave_sdo_write_exp8(slave, 0x4061, 2, 1) || - ecrt_slave_sdo_write_exp8(slave, 0x4061, 3, 1) || - ecrt_slave_sdo_write_exp8(slave, 0x4066, 0, 0) || - ecrt_slave_sdo_write_exp8(slave, 0x4067, 0, 4) || - ecrt_slave_sdo_write_exp8(slave, 0x4068, 0, 0) || - ecrt_slave_sdo_write_exp8(slave, 0x4069, 0, 25) || - ecrt_slave_sdo_write_exp8(slave, 0x406A, 0, 25) || - ecrt_slave_sdo_write_exp8(slave, 0x406B, 0, 50)) { - printk(KERN_ERR "Failed to configure SSI slave!\n"); - goto out_deactivate; - } -#endif - -#if 0 - printk(KERN_INFO "Writing alias...\n"); - if (ecrt_slave_sdo_write_exp16(slave, 0xBEEF)) { - printk(KERN_ERR "Failed to write alias!\n"); - goto out_deactivate; - } -#endif - -#ifdef ASYNC - // send once and wait... - ecrt_master_prepare_async_io(master); -#endif - -#if 1 - if (ecrt_master_start_eoe(master)) { - printk(KERN_ERR "Failed to start EoE processing!\n"); - goto out_deactivate; - } -#endif - - printk("Starting cyclic sample thread.\n"); - init_timer(&timer); - timer.function = run; - timer.expires = jiffies + 10; - add_timer(&timer); - - printk(KERN_INFO "=== Minimal EtherCAT environment started. ===\n"); - return 0; - -#if 1 - out_deactivate: - ecrt_master_deactivate(master); -#endif - out_release_master: - ecrt_release_master(master); - out_return: - return -1; -} - -/*****************************************************************************/ - -void __exit cleanup_mini_module(void) -{ - printk(KERN_INFO "=== Stopping Minimal EtherCAT environment... ===\n"); - - if (master) { - del_timer_sync(&timer); - printk(KERN_INFO "Deactivating master...\n"); - ecrt_master_deactivate(master); - ecrt_release_master(master); - } - - printk(KERN_INFO "=== Minimal EtherCAT environment stopped. ===\n"); -} - -/*****************************************************************************/ - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR ("Florian Pose "); -MODULE_DESCRIPTION ("EtherCAT minimal test environment"); - -module_init(init_mini_module); -module_exit(cleanup_mini_module); - -/*****************************************************************************/ - diff -r 7572c5bf7bb3 -r 342ad851ec78 rt/Makefile --- a/rt/Makefile Tue May 09 10:13:53 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -#------------------------------------------------------------------------------ -# -# Makefile -# -# $Id$ -# -# Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH -# -# This file is part of the IgH EtherCAT Master. -# -# The IgH EtherCAT Master is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; version 2 of the License. -# -# The IgH EtherCAT Master is distributed in the hope that it will be -# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with the IgH EtherCAT Master; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# -#------------------------------------------------------------------------------ - -ifneq ($(KERNELRELEASE),) - -#------------------------------------------------------------------------------ -# kbuild section -#------------------------------------------------------------------------------ - -ifneq ($(wildcard $(src)/rt.conf),) -include $(src)/rt.conf -else -MODULENAME := rt -endif - -obj-m := $(MODULENAME).o - -$(MODULENAME)-objs := msr_rt.o \ - rt_lib/msr-core/msr_lists.o \ - rt_lib/msr-core/msr_main.o \ - rt_lib/msr-core/msr_charbuf.o \ - rt_lib/msr-core/msr_reg.o \ - rt_lib/msr-core/msr_interpreter.o \ - rt_lib/msr-core/msr_messages.o \ - rt_lib/msr-core/msr_proc.o \ - rt_lib/msr-core/msr_error_reg.o \ - rt_lib/msr-utils/msr_utils.o \ - rt_lib/msr-utils/msr_time.o \ - rt_lib/msr-math/msr_base64.o \ - rt_lib/msr-math/msr_hex_bin.o \ - libm.o - -EXTRA_CFLAGS := -I$(src)/rt_lib/msr-include -D_SIMULATION \ - -I/usr/include -mhard-float \ - -DSVNREV=$(shell svnversion $(src)) -DUSER=$(USER) - -#------------------------------------------------------------------------------ - -else - -#------------------------------------------------------------------------------ -# default section -#------------------------------------------------------------------------------ - -ifneq ($(wildcard rt.conf),) -include rt.conf -else -MODULENAME := msr_rt -KERNEL := $(shell uname -r) -endif - -KERNELDIR := /lib/modules/$(KERNEL)/build - -modules: - $(MAKE) -C $(KERNELDIR) M=`pwd` - -clean: - $(MAKE) -C $(KERNELDIR) M=`pwd` clean - -install: - @./install.sh $(MODULENAME) $(KERNEL) - -#------------------------------------------------------------------------------ - -endif diff -r 7572c5bf7bb3 -r 342ad851ec78 rt/install.sh --- a/rt/install.sh Tue May 09 10:13:53 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -#!/bin/sh - -#------------------------------------------------------------------------------ -# -# Realtime module install script -# -# $Id: install.sh 5 2006-04-07 13:49:10Z fp $ -# -# Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH -# -# This file is part of the IgH EtherCAT Master. -# -# The IgH EtherCAT Master is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; version 2 of the License. -# -# The IgH EtherCAT Master is distributed in the hope that it will be -# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with the IgH EtherCAT Master; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# -#------------------------------------------------------------------------------ - -# Fetch parameters - -if [ $# -ne 2 ]; then - echo "Usage: $0 " - exit 1 -fi - -MODULENAME=$1 -KERNEL=$2 - -MODULESDIR=/lib/modules/$KERNEL/kernel/drivers/rt - -echo "Realtime installer" -echo " target: $MODULENAME" -echo " kernel: $KERNEL" - -# Create target directory - -if [ ! -d $MODULESDIR ]; then - echo " creating $MODULESDIR..." - mkdir $MODULESDIR || exit 1 -fi - -# Install files - -echo " installing $MODULENAME..." -if ! cp $MODULENAME.ko $MODULESDIR/$MODULENAME.ko; then exit 1; fi - -# Calculate dependencies - -echo " building module dependencies..." -depmod - -# Finish - -echo "done." -exit 0 - -#------------------------------------------------------------------------------ diff -r 7572c5bf7bb3 -r 342ad851ec78 rt/libm.o_shipped --- a/rt/libm.o_shipped Tue May 09 10:13:53 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -/usr/lib/libm.a \ No newline at end of file diff -r 7572c5bf7bb3 -r 342ad851ec78 rt/msr_load --- a/rt/msr_load Tue May 09 10:13:53 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -#!/bin/sh -module="msr_rt" -device="msr" -mode="664" - -# Group: since distributions do it differently, look for wheel or use staff -if grep '^staff:' /etc/group > /dev/null; then - group="staff" -else - group="wheel" -fi - -# invoke insmod with all arguments we got -# and use a pathname, as newer modutils don't look in . by default -/sbin/insmod -f ./$module.ko $* || exit 1 - -major=`cat /proc/devices | awk "\\$2==\"$device\" {print \\$1}"` - -echo $major -# Remove stale nodes and replace them, then give gid and perms -# Usually the script is shorter, it's scull that has several devices in it. - -rm -f /dev/${device} -mknod /dev/${device} c $major 0 -# ln -sf ${device}0 /dev/${device} -chgrp users /dev/${device} -chmod $mode /dev/${device} - - - - - - - - - diff -r 7572c5bf7bb3 -r 342ad851ec78 rt/msr_param.h --- a/rt/msr_param.h Tue May 09 10:13:53 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -/****************************************************************************** - * - * $Id$ - * - * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it - * and/or modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; version 2 of the License. - * - * The IgH EtherCAT Master is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - -#ifndef _MSR_PARAM_H_ -#define _MSR_PARAM_H_ - -#define MSR_ABTASTFREQUENZ 1000 - -#endif - -/*****************************************************************************/ diff -r 7572c5bf7bb3 -r 342ad851ec78 rt/msr_rt.c --- a/rt/msr_rt.c Tue May 09 10:13:53 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,296 +0,0 @@ -/****************************************************************************** - * - * m s r _ r t . c - * - * Kernelmodul für 2.6 Kernel zur Meßdatenerfassung, Steuerung und Regelung. - * - * $Id$ - * - * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH - * - * This file is part of the IgH EtherCAT Master. - * - * The IgH EtherCAT Master is free software; you can redistribute it - * and/or modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; version 2 of the License. - * - * The IgH EtherCAT Master is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the IgH EtherCAT Master; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - *****************************************************************************/ - -// Linux -#include -#include -#include -#include -#include - -// RT_lib -#include -#include -#include -#include -#include -#include -#include "msr_param.h" - -// EtherCAT -#include "../include/ecrt.h" - -#define ASYNC - -// Defines/Makros -#define HZREDUCTION (MSR_ABTASTFREQUENZ / HZ) - -/*****************************************************************************/ -/* Globale Variablen */ - -// Adeos -static struct ipipe_domain this_domain; -static struct ipipe_sysinfo sys_info; - -// EtherCAT -ec_master_t *master = NULL; -ec_domain_t *domain1 = NULL; - -// Prozessdaten -void *r_ssi; -void *r_ssi_st; - -// KanŽäle -uint32_t k_ssi; -uint32_t k_ssi_st; - -ec_field_init_t domain1_fields[] = { - {&r_ssi, "0:3", "Beckhoff", "EL5001", "InputValue", 0}, - {&r_ssi_st, "0:3", "Beckhoff", "EL5001", "Status", 0}, - {} -}; - -/*****************************************************************************/ - -static void msr_controller_run(void) -{ -#ifdef ASYNC - // Empfangen - ecrt_master_async_receive(master); - ecrt_domain_process(domain1); -#else - // Senden und empfangen - ecrt_domain_queue(domain1); - ecrt_master_run(master); - ecrt_master_sync_io(master); - ecrt_domain_process(domain1); -#endif - - // Prozessdaten verarbeiten - k_ssi = EC_READ_U32(r_ssi); - k_ssi_st = EC_READ_U8 (r_ssi_st); - -#ifdef ASYNC - // Senden - ecrt_domain_queue(domain1); - ecrt_master_run(master); - ecrt_master_async_send(master); -#endif -} - -/*****************************************************************************/ - -int msr_globals_register(void) -{ - msr_reg_kanal("/ssi_position", "", &k_ssi, TUINT); - msr_reg_kanal("/ssi_status", "", &k_ssi_st, TUINT); - return 0; -} - -/*****************************************************************************/ - -void msr_run(unsigned irq) -{ - static int counter = 0; - - MSR_ADEOS_INTERRUPT_CODE(msr_controller_run(); msr_write_kanal_list();); - - ipipe_control_irq(irq, 0, IPIPE_ENABLE_MASK); // Interrupt bestŽätigen - if (++counter >= HZREDUCTION) { - ipipe_propagate_irq(irq); // und weiterreichen - counter = 0; - } -} - -/*****************************************************************************/ - -void domain_entry(void) -{ - printk("Domain %s started.\n", ipipe_current_domain->name); - - ipipe_get_sysinfo(&sys_info); - ipipe_virtualize_irq(ipipe_current_domain,sys_info.archdep.tmirq, - &msr_run, NULL, IPIPE_HANDLE_MASK); - - ipipe_tune_timer(1000000000UL / MSR_ABTASTFREQUENZ, 0); -} - -/*****************************************************************************/ - -int __init init_rt_module(void) -{ - struct ipipe_domain_attr attr; //ipipe -#if 1 - ec_slave_t *slave; -#endif - - // Als allererstes die RT-Lib initialisieren - if (msr_rtlib_init(1, MSR_ABTASTFREQUENZ, 10, &msr_globals_register) < 0) { - printk(KERN_ERR "Failed to initialize rtlib!\n"); - goto out_return; - } - - if ((master = ecrt_request_master(0)) == NULL) { - printk(KERN_ERR "Failed to request master 0!\n"); - goto out_msr_cleanup; - } - - //ecrt_master_print(master, 2); - - printk(KERN_INFO "Creating domains...\n"); - if (!(domain1 = ecrt_master_create_domain(master))) { - printk(KERN_ERR "Failed to create domains!\n"); - goto out_release_master; - } - - printk(KERN_INFO "Registering domain fields...\n"); - if (ecrt_domain_register_field_list(domain1, domain1_fields)) { - printk(KERN_ERR "Failed to register domain fields.\n"); - goto out_release_master; - } - - printk(KERN_INFO "Activating master...\n"); - if (ecrt_master_activate(master)) { - printk(KERN_ERR "Could not activate master!\n"); - goto out_release_master; - } - -#if 0 - if (ecrt_master_start_eoe(master)) { - printk(KERN_ERR "Failed to start EoE processing!\n"); - goto out_deactivate; - } -#endif - -#if 0 - if (ecrt_master_fetch_sdo_lists(master)) { - printk(KERN_ERR "Failed to fetch SDO lists!\n"); - goto out_deactivate; - } - ecrt_master_print(master, 2); -#else - ecrt_master_print(master, 0); -#endif - -#if 1 - if (!(slave = ecrt_master_get_slave(master, "0:3"))) { - printk(KERN_ERR "Failed to get slave!\n"); - goto out_deactivate; - } - - if ( - ecrt_slave_sdo_write_exp8(slave, 0x4061, 1, 1) || // disable frame error bit - ecrt_slave_sdo_write_exp8(slave, 0x4061, 2, 0) || // power failure bit - ecrt_slave_sdo_write_exp8(slave, 0x4061, 3, 1) || // inhibit time - ecrt_slave_sdo_write_exp8(slave, 0x4061, 4, 0) || // test mode - ecrt_slave_sdo_write_exp8(slave, 0x4066, 0, 1) || // dualcode - ecrt_slave_sdo_write_exp8(slave, 0x4067, 0, 5) || // 125kbaud - ecrt_slave_sdo_write_exp8(slave, 0x4068, 0, 0) || // single-turn - ecrt_slave_sdo_write_exp8(slave, 0x4069, 0, 25) || // frame size - ecrt_slave_sdo_write_exp8(slave, 0x406A, 0, 25) || // data length - ecrt_slave_sdo_write_exp16(slave, 0x406B, 0, 30000) // inhibit time in us - ) { - printk(KERN_ERR "Failed to configure SSI slave!\n"); - goto out_deactivate; - } -#endif - -#if 0 - if (!(slave = ecrt_master_get_slave(master, "1:0"))) { - printk(KERN_ERR "Failed to get slave!\n"); - goto out_deactivate; - } - if (ecrt_slave_write_alias(slave, 0x5678)) { - printk(KERN_ERR "Failed to write alias!\n"); - goto out_deactivate; - } -#endif - -#ifdef ASYNC - // Einmal senden und warten... - ecrt_master_prepare_async_io(master); -#endif - - ipipe_init_attr(&attr); - attr.name = "IPIPE-MSR-MODULE"; - attr.priority = IPIPE_ROOT_PRIO + 1; - attr.entry = &domain_entry; - ipipe_register_domain(&this_domain, &attr); - return 0; - -#if 1 - out_deactivate: - ecrt_master_deactivate(master); -#endif - out_release_master: - ecrt_release_master(master); - out_msr_cleanup: - msr_rtlib_cleanup(); - out_return: - return -1; -} - -/*****************************************************************************/ - -void __exit cleanup_rt_module(void) -{ - printk(KERN_INFO "Cleanign up rt module...\n"); - - ipipe_tune_timer(1000000000UL / HZ, 0); // Alten Timertakt wiederherstellen - ipipe_unregister_domain(&this_domain); - - printk(KERN_INFO "=== Stopping EtherCAT environment... ===\n"); - ecrt_master_deactivate(master); - ecrt_release_master(master); - printk(KERN_INFO "=== EtherCAT environment stopped. ===\n"); - - msr_rtlib_cleanup(); -} - -/*****************************************************************************/ - -#define EC_LIT(X) #X -#define EC_STR(X) EC_LIT(X) -#define COMPILE_INFO "Revision " EC_STR(SVNREV) \ - ", compiled by " EC_STR(USER) \ - " at " __DATE__ " " __TIME__ - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR ("Florian Pose "); -MODULE_DESCRIPTION ("EtherCAT real-time test environment"); -MODULE_VERSION(COMPILE_INFO); - -module_init(init_rt_module); -module_exit(cleanup_rt_module); - -/*****************************************************************************/ - -/* Emacs-Konfiguration -;;; Local Variables: *** -;;; c-basic-offset:4 *** -;;; End: *** -*/ diff -r 7572c5bf7bb3 -r 342ad851ec78 rt/msr_unload --- a/rt/msr_unload Tue May 09 10:13:53 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -#!/bin/sh -module="msr_rt" -device="msr" - -# invoke rmmod with all arguments we got -/sbin/rmmod $module $* || exit 1 - -# Remove stale nodes -rm -f /dev/${device} /dev/${device}0 diff -r 7572c5bf7bb3 -r 342ad851ec78 rt/msrserv.pl --- a/rt/msrserv.pl Tue May 09 10:13:53 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,257 +0,0 @@ -#!/usr/bin/perl -w - -#------------------------------------------------------------------------------ -# -# Copyright (C) 2006 Ingenieurgemeinschaft IgH -# -# This file is part of the IgH EtherCAT Master. -# -# The IgH EtherCAT Master is free software; you can redistribute it -# and/or modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; version 2 of the License. -# -# The IgH EtherCAT Master is distributed in the hope that it will be -# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with the IgH EtherCAT Master; if not, write to the Free Software -# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -# -#------------------------------------------------------------------------------ -# -# Multithreaded Server -# according to the example from "Programming Perl" -# this code is improved according to the example from -# perldoc perlipc, so now safely being usable under Perl 5.8 -# (see note (*)) -# -# works with read/write on a device-file -# -#------------------------------------------------------------------------------ - -require 5.002; -use strict; -BEGIN { $ENV{PATH} = '/opt/msr/bin:/usr/bin:/bin' } -use Socket; -use Carp; -use FileHandle; -use Getopt::Std; - -use Sys::Syslog qw(:DEFAULT setlogsock); - -use vars qw ( - $self $pid $dolog $port $dev %opts $selfbase - $len $offset $stream $written $read $log $blksize - $instdir - $authfile %authhosts - ); - - -# Do logging to local syslogd by unix-domain socket instead of inetd -setlogsock("unix"); - -# Prototypes and some little Tools -sub spawn; -sub logmsg { - my ($level, $debug, @text) = @_; - syslog("daemon|$level", @text) if $debug > $dolog; -# print STDERR "daemon|$level", @text, "\n" if $dolog; -} -sub out { - my $waitpid = wait; - logmsg("notice", 2, "$waitpid exited"); - unlink "$selfbase.pid"; - exit 0; -} - -sub help { - print "\n usage: $0 [-l og] [-h elp] [-p port] [-d device]\n"; - exit; -} - -# Process Options -%opts = ( - "l" => 1, - "h" => 0, - "p" => 2345, - "d" => "/dev/msr" - ); - -getopts("lhp:d:", \%opts); - -help if $opts{"h"}; - -( $self = $0 ) =~ s+.*/++ ; -( $selfbase = $self ) =~ s/\..*//; -$log = "$selfbase.log"; -$dolog = $opts{"l"}; -$port = $opts{"p"}; -$dev = $opts{"d"}; -$blksize = 1024; # try to write as much bytes -$instdir = "/opt/msr"; -$authfile = "$instdir/etc/hosts.auth"; - -# Start logging -openlog($self, 'pid'); - -# Flush Output, dont buffer -$| = 1; - -# first fork and run in background -if ($pid = fork) { -# open LOG, ">$log" if $dolog; -# close LOG; - logmsg("notice", 2, "forked process: $pid\n"); - exit 0; -} - -# Server tells about startup success -open (PID, ">/$instdir/var/run/$selfbase.pid"); -print PID "$$\n"; -close PID; - -# Cleanup on exit (due to kill -TERM signal) -$SIG{TERM} = \&out; - -# We use streams -my $proto = getprotobyname('tcp'); - -# Open Server socket -socket(Server, PF_INET, SOCK_STREAM, $proto) or die "socket: $!"; -setsockopt(Server, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)) - or die "setsocketopt: $!"; -bind (Server, sockaddr_in($port, INADDR_ANY)) - or die "bind: $!"; -listen (Server, SOMAXCONN) - or die "listen: $!"; - -%authhosts = (); -# get authorized hosts -open (AUTH, $authfile) - or logmsg ("notice", 2, "Could not read allowed hosts file: $authfile"); -while () { - chomp; - my $host = lc $_; - if ($host =~ /^[\d\w]/) { - $authhosts{$_} = 1; - logmsg ("notice", 2, "Authorized host: >$host<"); - } -} -close (AUTH); - -# tell about open server socket -logmsg ("notice", 2, "Server started at port $port"); - -my $waitedpid = 0; -my $paddr; - -# wait for children to return, thus avoiding zombies -# improvement (*) -use POSIX ":sys_wait_h"; -sub REAPER { - my $child; - while (($waitedpid = waitpid(-1,WNOHANG)) > 0) { - logmsg ("notice", 2, "reaped $waitedpid", ($? ? " with exit $?" : "")); - } - $SIG{CHLD} = \&REAPER; # loathe sysV -} - -# also all sub-processes should wait for their children -$SIG{CHLD} = \&REAPER; - -# start a new server for every incoming request -# improvement (*) -- loop forever - -while ( 1 ) { - for ( $waitedpid = 0; - ($paddr = accept(Client,Server)) || $waitedpid; - $waitedpid = 0, close Client ) { - next if $waitedpid and not $paddr; - my ($port, $iaddr) = sockaddr_in($paddr); - my $name = lc gethostbyaddr($iaddr, AF_INET); - my $ipaddr = inet_ntoa($iaddr); - my $n = 0; - -# tell about the requesting client - logmsg ("info", 2, "Connection from >$ipaddr< ($name) at port $port"); - - spawn sub { - my ($head, $hlen, $pos, $pegel, $typ, $siz, $nch, $nrec, $dat, $i, $j, $n, $llen); - my ($watchpegel, $shmpegel); - my ($rin, $rout, $in, $line, $data_requested, $oversample); - my (@channels); - -# to use stdio on writing to Client - Client->autoflush(); - -# Open Device - sysopen (DEV, "$dev", O_RDWR | O_NONBLOCK, 0666) or die("can't open $dev"); - -# Bitmask to check for input on stdin - $rin = ""; - vec($rin, fileno(Client), 1) = 1; - -# check for authorized hosts - my $access = 'deny'; - $access = 'allow' if $authhosts{$ipaddr}; - $line = "\n"; - logmsg ("info", 2, $line); - $len = length $line; - $offset = 0; - while ($len) { - $written = syswrite (DEV, $line, $len, $offset); - $len -= $written; - $offset += $written; - } - - while ( 1 ) { - $in = select ($rout=$rin, undef, undef, 0.0); # poll client -# look for any Input from Client - if ($in) { -# exit on EOF - $len = sysread (Client, $line, $blksize) or exit; - logmsg("info", 0, "got $len bytes: \"$line\""); - $offset = 0; -# copy request to device - while ($len) { - $written = syswrite (DEV, $line, $len, $offset); - $len -= $written; - $offset += $written; - } - } -# look for some output from device - if ($len = sysread DEV, $stream, $blksize) { - print Client $stream; - } else { - select undef, undef, undef, 0.1; # calm down if nothing on device - } - } - }; - logmsg("info", 2, "spawned\n"); - } - logmsg("info", 2, "server loop\n"); -} - -sub spawn { - my $coderef = shift; - - unless (@_ == 0 && $coderef && ref($coderef) eq 'CODE') { - confess "usage: spawn CODEREF"; - } - my $pid; - if (!defined($pid = fork)) { - logmsg ("notice", 2, "fork failed: $!"); - return; - } elsif ($pid) { - logmsg ("notice", 2, "Request $pid"); - return; # Parent - } - -# do not use fdup as in the original example -# open (STDIN, "<&Client") or die "Can't dup client to stdin"; -# open (STDOUT, ">&Client") or die "Can't dup client to stdout"; -# STDOUT->autoflush(); - exit &$coderef(); -} diff -r 7572c5bf7bb3 -r 342ad851ec78 rt/rt.conf.tmpl --- a/rt/rt.conf.tmpl Tue May 09 10:13:53 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -#------------------------------------------------------------------------------ -# -# Configuration file for msr realtime modules -# -# $Id$ -# -# This file is a versioned template configuration. Copy it to "rt.conf" -# (which is ignored by Subversion) and adjust it to your needs. -# -#------------------------------------------------------------------------------ - -# Module name (without extension) -MODULENAME := ec_rt_sample - -# The kernel to compile the EtherCAT sources against -KERNEL := `uname -r` - -#------------------------------------------------------------------------------