next_inactive up previous


EPICS on a TS5500 PC104 CPU Running Linux

A. Freyberger

Abstract:

Details on getting EPICS running on a TS5500 pc104 cpu are presented. Including device support for the on-board digital input and output lines [DIO] and analog to digital converters [ADC]. This work is geared toward a specific application, however the TS5500 is a general purpose device and probably has other applications. In the final sections details on EPICS development for a Linux based IOC are presented.

1 Introduction

The TS5500 PC1041 CPU available from Technologic Systems is a small single board computer [SBC] consisting of 133MHz 586 processor and has on board eight 12-bit ADCs, 38 digital input/output lines, three RS232 serial ports, two USB ports and a PCMCIA slot2. The TS5500 can be purchased with Linux pre-installed or other operating systems. EPICS as of release 3.14 now runs on Linux operating systems, can the TS5500 be turned into an EPICS IOC???

For those who do not care for the details of Epics/Linux, but just want to get a TS5500 on-line as soon as possible the next section should be sufficient. Work on providing compact flash images for other TS5?00 SBC is in progress.

The following sections describe the steps needed to develop device support for the ADC and DIO lines on the TS5500. First a description of how to build EPICS R3.14.? on your Linux box and set it up for local development. Then the device support for the ADC will be presented. The details of the DIO device support follow. The open issues of using these devices for controls will be presented in the final section.

2 For the Impatient

For immediate deployment of a TS5500 in the field, EPICS support has been macro'ized so that all one needs to do is overwrite the compact flash with a copy that I'll make available. With an EPICS compact flash, the user then needs to adjust the network parameters and change the EPICS record name prefix so that the EPICS database records have unique names. Then a reboot3 and the device should be up and running. This will result 19 digital inputs, 8 digital outputs and 8 ADC EPICS records available on the network. There are additional 11 DIO channels available, but device support has not been written for these channels yet4.

2.1 TS5500 options/requirements

When purchasing a TS5500 the following options need to be specified:

memory
32MBytes is sufficient.
compact flash
32Mbytes sufficient, 64Mbytes is more than sufficient.
ADC
[optional] order the adc option if you want eight channels of 12bit ADCs.
enclosure
[optional] the metal enclosure is a nice package if the SBC is not to be embedded in an existing chassis.
power supply
[optional] any 5V DC power supply will work [1Amp]. Not needed if you order the enclosure or if the SBC is embedded in a chassis that already has +5V available.
linux_preinstall
[optional] We will overwrite the compact flash that comes with the TS5500 so it doesn't matter if linux is pre-installed or not. But get this if you want to play with the TS5500.

2.2 Network configuration

To change the TS5500 network configuration, you will need to:

  1. get a valid IP address on the appropriate subnet.
  2. Hook up a terminal to the com2 port and the Ethernet port to the Ethernet.
  3. Boot the TS5500, using the com2 port to watch the boot process.
  4. Log in as root.
  5. edit the following files, the vi editor is available on the SBC5:

    1. /etc/sysconfig/network_cfg
    2. /etc/sysconfig/ifcfg_eth0
    3. /etc/rc.d/rcS.sysinit

      1. change host name at end of script
      2. comment out loading the a2d_driver if your TS5500 does not have an ADC.

2.3 database definitions

Every EPICS record must have an unique name. To give the database records an unique name do the following:

  1. edit /usr/local/epics/iocBoot/ts5500/st.cmd using the vi editor, and change ``default'' to something that you know will be unique [ie the hostname of the TS5500]. Note comment out the ts5500_ai.db if your TS5500 does not have the optional ADC.

    1. dbLoadRecords("/usr/local/epics/db/ts5500_ai.db", ``prefix=default'')
    2. dbLoadRecords("/usr/local/epics/db/ts5500_bi.db", ``prefix=default'')
    3. dbLoadRecords("/usr/local/epics/db/ts5500_bo.db", ``prefix=default'')
If you want more specific EPICS record names than my_host_adc_0, you can edit the database files found in /usr/local/epics/db. If you want to change the configuration of the ADC channels [5 or 10 Volt ranges, uni or bi polar] you will need to edit ts5500_ai.db. The default ADC channel configuration is set up in the ts5500_ai.db file as follows:

Channels 0 & 4
+/-10V bipolar
# +/- 10V bipolar
field(INP, "#C0 S0 @0")
field(ESLO, "0.0048828")
Channels 1& 5
+/-5V bipolar
# +/- 5V bipolar
field(INP, "#C0 S1 @1")
field(ESLO, "0.002442")
Channels 2& 6
+10 V unipolar
# 0->10V unipolar
field(INP, "#C0 S2 @2")
field(ESLO, "0.002441")
Channels 3 & 7
+5V unipolar
# 0->5V unipolar
field(INP, "#C0 S3 @3")
field(ESLO, "0.001221")

2.4 medm and StripTool screens

The TS5500 is also running a webserver, so one can serve the ``adl'' files via http. Pointing a web browser to http://hostname.jlab.org/ts5500.adl will result in the adl file being sent to your browser, not very helpful. But you can save that to file named ts5500.adl and then execute:

medm -x -macro ``prefix=default'' ts5500.adl >& /dev/null & 

and you will be happy. Remember to change default in the command above to whatever the prefix is changed to in the database files. The resulting medm screen is shown in Figure 1 and a StripTool capturing a toggle of a digital output that happens to be connected to an ADC channels in shown in Figure 2.

Figure 1: medm screen for the TS5500 DIO channels and eight 12bit ADC channels. The DIO channels utilize the DIO1 and DIO2 ports on the SBC, there are additional DIO channels available on the LCD port. If you want to make use of the LCD port for DIO channels software will have to be written.
Image /tmp/lyx_tmpdir1774156jv4F/lyx_tmpbuf0/_u_site_www_html_accel_beam_diag_pc104_TS5500_ts5500_adl.jpg

Figure 2: StripTool showing the value of a DIO output [blue] and the read back of an ADC. The DIO output was toggle on/off by a perl script on a unix host computer. The output of the DIO was connected to the ADC input.

Image /tmp/lyx_tmpdir1774156jv4F/lyx_tmpbuf0/_u_site_www_html_accel_beam_diag_pc104_TS5500_striptool.jpg

2.5 Summary

This results in a set of very simple EPICS records. One can add additional database [software] records for more complicating activities. Adding new database records consists of adding or modifying the files in /usr/local/bin/epics/db and modifying /usr/local/bin/epics/iocBoot/ts5500/st.cmd accordingly. The EPICS State Notation Language [SNC] code has been ported to Linux/EPICS-3.14 as well for state machine applications. SNC code will require a complete recompile of the iocCore executable. For that you will need to read the rest of this document and a bit more.

In addition to the DIO and ADC channels the TS5500 has three RS232 ports of which two are available for controlling serial devices. The SBC has an application called ``minicom'' that allows one to communicate over these ports or one can write EPICS support for integration into the control system.

3 EPICS R3.14.? on Linux Desktop and SBC

The following sections deal with developing EPICS software for the TS5500 SBC in a Linux environment. Presently most EPICS software on site is developed for VxWorks targets. VxWorks licenses are expensive. The TS5500 provides an inexpensive way to learn EPICS as the cross compilers are free and the hardware is about a factor of ten cheaper then VME hardware6.

Even though the TS5500 SBC runs Linux, it does not have a full Linux install so one still needs a host computer to compile software and then the resulting executables are copied to the TS5500 and executed. In principle this can be any computer with GCC appropriately configured to cross compile for 586 targets. In practice this means almost any PC running Linux is already setup as a host computer. There are some issues with the different versions of GCC and EPICS, but if you are running Redhat9 or Fedora Core2 you should be OK [don't try this on a Redhat8 machine].

3.1 EPICS Host build

The steps to building R3.14.2 have been posted on the archive previously7, the steps for getting R3.14.2 should still be close to correct for the more recent versions of 3.14.?. I'd recommend going with the latest version available as there has been a large amount of progress on R3.14 tree. The steps for R3.14.2 are:

  1. Get the source: baseR3.14.2.tar.gz from
    epics base http://www.aps.anl.gov/epics/downloads/base/baseR3.14.2.tar.gz [you will need to log in/register]
  2. make a directory for your build: /path/to/R3.14.2
  3. cd in the directory, and copy/move the R3.14.2 tarball into that directory.
  4. untar it and build via:

    1. tar -zxvf baseR3.14.2.tar.gz
    2. cd base-3.14.2
    3. setenv EPICS_BASE $PWD
    4. source startup/Site.cshrc
    5. edit configure/CONFIG_SITE and change STATIC_BUILD=NO to STATIC_BUILD=YES, this way you can move the resulting binaries to other linux-x86 platforms [like a pc104 card] and they will run without needed to find shared libraries.
    6. make
  5. make example ioc shell code and boot scripts

    1. bin/linux-x86/makeBaseApp.pl -b $EPICS_BASE -t example iocname
    2. bin/linux-x86/makeBaseApp.pl -b $EPICS_BASE -i -t example iocname
    3. cd [iocname]App
    4. make
    5. cd ../iocBoot/ioc[iocname]
    6. chmod +x st.cmd
    7. ./st.cmd

      1. this will fire up the epics ioc shell.....if this results in an epics> prompt...you're looking pretty
      2. at the epics> prompt type ``dbl'' to see the database records loaded in this example.
      3. if you want, on some host, direct your EPICS_CA_ADDR_LIST to ``iocname'' and from there you can ``caget'' or StripTool the records being processed on your linux ioc.

3.2 Moving to the TS5500 SBC

In the previous section the EPICS example app was built and executed on the host computer. Now we must move the application to the SBC. Transferring files between the TS5500 and the host computer can be accomplished in many ways:

Compact Flash
Attach the compact flash to the host computer and write to the compact flash
FTP
proftp, the TS5500 is running a ftp server. Disable this as soon as secure shell is up and running.
secure shell
install and use secure shell, Technologic provides secure shell binaries that you should download to the TS5500 as soon as possible.
NFS
export the host computer disk to the TS5500
For development purposes the NFS option is the most convenient. To test your executables, you log onto the TS5500, mount the volume exported by the host, cd into the appropriate directory /host/path/to/R3.14.2/iocBoot/ioc[iocname] and run your code [./st.cmd]. When done with development, essential pieces of code and supporting files must be copied to the TS5500 compact flash so that it can run EPICS without relying on NFS mounts being available. Look in the st.cmd file to see which files are needed and modify the relative paths so that st.cmd can be executed from any directory. Details will be shown after the device support for the ADC and DIO are presented.

3.3 Defining your EPICS environment

The build above results in a base build which you can work within if you so desire. Most developers use a more structured approach where the epics build resides in a safe place and an application development area that resides in a separate distinct area [preferably under the developers control]. This is usually accomplished by having an $EPICS (application area) and an $EPICS_BASE (base area) environment variables. This also helps migrating the application to the SBC since the necessary files are no longer buried in the base build. This works for R3.14.? as well. In the application area ($EPICS) the following subdirectories are found:

app
sub-directories under app correspond to distinct ioc configurations, manually created/maintained.
bin
automatically generated by the Makefile. Binaries are in the linux-x86
db
database files which are in app/app_name/Db directory get installed in this common directory by the Makefile. These are referenced and used by the st.cmd script.
dbd
dbd files in /app/app_name/src get installed here by the Makefile.
dev
device support routines go here. One sub-directory for each device support. Manually created and maintained.
include
header files for record support get migrated here by the Makefile.
iocBoot
contains the startup script for your IOCs, manually created and maintained.
lib
support libs for device support are found here. Makefile takes care of this.
scripts
contains Site.cshrc which defines your environment appropriately [source Site.cshrc].
The following directories should be managed by a code management system [cvs] so that one can track changes, app, dev, iocBoot, scripts. The directories, bin, db, dbd, include, lib do not have to managed as they are made by the Makefile8.

4 TS5500 and EPICS device support

Technologic systems provides a Linux kernel driver for the eight on-board ADC channels. The driver supports two ranges, 5V and 10V as well as two polarities, uni-polar and bi-polar. The ADC can be read out at kHz rates. For the purposes of ``ai'' device support, which is processed at most five times a second, we ignore this capability. Rewriting the Linux char driver as a block memory driver would allow one to sample at a high rate and store the results in a waveform record. The DIO channels are access via direct memory read/writes9. The source files for TS5500 device support are located under $EPICS/dev/TS5500, in which you will find:

a2d_driver.h
adc driver header file from Technologic website.
bit_utils.c
simple bit manipulation functions
devAiTS5500.c
device support for the ADC
devBiTS5500.c
digital input device support
devBoTS5500.c
digital output device support
Makefile
mysterious file from the EPICS community, execute make and the code is compiled and dinner is served.
TS5500Include.dbd
This file pulls in base.dbd for all the support records as well as the TS5500Support.dbd for a complete dbd file.
TS5500Main.cpp
The ``main'' program, a copy of the ExampleMain.cpp created during the R3.14.2 build phase.
TS5500Support.dbd
defines the record to device support mapping.
The source for the device support will be described in the following sections. The TS5500Support.dbd is as follows:

###############################################

#  device support

###############################################

#TS5500 on-board devices

device(ai,VME_IO,devAiTS5500,"TS5500_A2D")

device(bi,VME_IO,devBiTS5500,"TS5500_DIO")

device(bo,VME_IO,devBoTS5500,"TS5500_DIO")

#

The source for TS5500Include.dbd looks like:

include "base.dbd"

include "TS5500Support.dbd"

5 TS5500 ADC Device Support

As mentioned Technologic System provides a Linux kernel driver for the ADC channels. EPICS device support involves using this ``character'' driver to make this data available via EPICS. The ADC device nodes are created in /dev/ADC/0 ... /dev/ADC/7 and EPICS device support involves opening these devices, writing to them and reading from them. In addition ``ioctl'' is used for configuration. This is typical for Linux character devices. Note since the device support invokes only ``user'' calls this EPICS application does not have to be executed by ``root''.

For the ADC the analog input record is used [ai]. The device support initialization [init_record] consists of deciphering the INP field to configure the ADC range and polarity for each channel. The device support processing [read_ai] consists of reading the channel and posting the result. As of this writing the auto configuration the ESLO field [slope] is not working and this must be properly defined in the database file. The file devAiTS5500.c consists of 200 lines of code and comments and does not look that different than VME device support. The source for devAiTS5500.c is shown presented at the end of the paper and can be accessed electronically via.....

6 TS5500 DIO EPICS Device Support

The digital input and output device support is not as clean as the device support for the ADC. The DIO ports are accessed by direct memory reads and writes and as such this application must be executed as root. One should write a Linux character driver for these ports, thereby allowing the EPICS application to be run in user space. The 38 DIO channels are distributed over three connector headers labels DIO1, DIO2 and LCD. Some channels are hardwired as inputs and outputs, but most can be configured [in groups of four] as either inputs or outputs. The LCD header is meant to drive a small LCD text screen and is configured in a weird way, so device support has not been implemented yet for these DIO channels. For the channels on DIO1 and DIO2 header, the device support configures the first eight channels on each header as inputs, the next four as outputs and the remaining odd channels are hardwired as inputs. This gives roughly two inputs for every outputs. This can be changed of course by modifying the source code if one desires a different ratio on outputs to inputs.

The source is listed at the end of the paper.

7 TS5500 as an IOC

The three device support routines are located in the /dev/TS5500 directory. Executing ``make'' results in a library named libTS5500Support.a which can now be linked into an iocCore. Additionally TS5500Support.dbd is created in the $(EPICS)/dbd area. The final step is creating an application in $(EPICS)/app, for example ``ts5500''. In $(EPICS)/app/ts5500 there will be a src area for any additional SNC or other code, a Db for the databases and perhaps a medm area for the screens.

The src area should contain a ts5500Include.dbd file that holds all the database definitions that your application will be using. which in this case looks like:

include "base.dbd" 

include "../../../../dev/TS5500/TS5500Support.dbd"

The Makefile in the src area looks like:

TOP=../../..

include $(TOP)/configure/CONFIG

#--------------------

#  ADD MACRO DEFINITIONS AFTER THIS LINE

#=============================

#=============================

# build an ioc application

PROD_IOC = ts5500

# <name>.dbd will be created from <name>Include.dbd

DBD += ts5500.dbd

# <name>_registerRecordDeviceDriver.cpp will be created from <name>.dbd

ts5500_SRCS += ts5500_registerRecordDeviceDriver.cpp

ts5500_SRCS_DEFAULT += ts5500Main.cpp

ts5500_SRCS_vxWorks += -nil-

#

ts5500_LIBS += TS5500Support

ts5500_LIBS += $(EPICS_BASE_IOC_LIBS)

#===========================

include $(TOP)/configure/RULES

This results in an executable in bin/linux-86 named ts5500. The next thing is to create the st.cmd script, which looks like:

#!/usr/local/epics/bin/linux-x86/ts5500

## The names of the binary above and .dbd file below will be incorrect

## unless you used the same names for the ioc and the app directory.

# create and register all record/device/driver/registrar support

dbLoadDatabase("/usr/local/epics/dbd/ts5500.dbd",0,0)

registerRecordDeviceDriver(pdbbase)

dbLoadRecords("/usr/local/epics/db/ts5500_ai.db", "prefix=casa-apf2")

dbLoadRecords("/usr/local/epics/db/ts5500_bi.db", "prefix=casa-apf2")

dbLoadRecords("/usr/local/epics/db/ts5500_bo.db", "prefix=casa-apf2")

iocInit()

## Start sequence programs here, if there are any

#

This is the startup script as it exists on the SBC compact flash. From this we see that the following files ts5500, ts5500.dbd, ts5500_ai.db, ts5500_bi.db, and ts5500_bo.db must be copied over to the SBC. In addition caRepeater which was built during the EPICS_BASE build should be copied to /usr/local/bin/ so that it resides in root's nominal path. Note that the executable ts5500 is a static binary, there is no ld of driver or device support during the EPICS load process as there is on a VxWorks based system. This must be done ahead of time by adding the appropriate library to the ts5500_LIBS line in the Makefile.

7.1 Starting the EPICS shell

In order for the EPICS shell to get started upon reboot of the SBC a shell script has been written in the /etc/init.d area. This shell script gets executed at the end of ``runlevel 3''. Developers will want to disable this, by removing the softlink in the /etc/rc.d/rc3.d that points to this script.

To launch the EPICS shell, execute the st.cmd script as root. That is: /usr/local/epics/iocBoot/ts5500/st.cmd will drop you into the interactive epics shell. In order to get this shell to execute without being attached to a terminal some chicanery needs to invoked. Specifically within /etc/init.d/Epics.script one sees the line: sleep 99999d | $epics >& /dev/null &10. This line is waiting for an answer from the 99999days of sleep or the EPICS shell. If the EPICS shell does not crash, it will be terminated after 99999days or 273years, I doubt the Hampton Roads area will go that long without a power outage. Personally I'd like a more elegant/robust solution.

8 EPICS/Linux/PC104 issues

Using PC104 SBC for IOCs is still in its infancy. Using Linux as a operating system for EPICS application is also rather novel. So far the following EPICS applications have been successfully deployed on a PC104 SBC running Linux, serial port control of devices, SNC code, device support for daughter cards and the device support presented here. There are still a few things to try. For example: the TS5500 has inputs that will raise an interrupt level, associating an interrupt service routine to this would be a useful feature within the JLAB control environment11. The TS5500 can also come with a watchdog timer, which might have some use around the lab.

The Linux operating system on the TS5500 is not a real time OS. Any application that has a strict real-time requirement might not be satisfied by the TS5500. However, timing studies should be performed. Since the TS5500 SBC will not be loaded with as many applications as a typical VME crate it might be that the tasks are executed sufficiently fast to meet the requirement.

The EPICS software development environment can be made similar to the existing VxWorks environment such that developers do not suffer culture shock moving between the two environments. Debugging software on the SBC has been easier due to the fact that the SBC typically is running fewer [zero] applications and one can simply kill the EPICS application and restart it [no reboots required]. The application presented [35 database records, each scanned at a 5Hz rate] here utilizes less than 5% of the available CPU cycles and a few MBytes of memory.

9 Conclusions

Epics device support for on-board DIOs and ADCs on the TS5500 SBC has been successfully demonstrated. A software development model similar to existing EPICS development models using VxWorks has been developed and used in the course of this work. This development model should work with a group of concurrent developers although so far it has been used by a single user.

The TS5500 appears to be an inexpensive useful generic device which just on its own [no daughter cards] could be used for valve control[DIO], viewer control [DIO], power supply control [serial] or any other applications with modest DIO/ADC or serial requirements. This software was written for the Hall-A current calorimeter where the TS5500 and two Sensoray S518 daughter boards will be used to for 16 channels of thermometry [S518], selonoid control [DIO], interlock and position readbacks [DIO]. heater control [serial] and chiller control [serial]. A document on developing Linux drivers and EPICS device support for the Sensoray S518 PC104 daughter card is being written.

10 ToDo:

Not in any specific order.

  1. write Linux character driver for DIO, rewrite EPICS device support.
  2. get ESLO set correctly by devAiTS5500.c so it can be removed from the db file.
  3. make CVS repository available to JLAB [offsite?] and on the web.
  4. write sensoray S518 daughter card document.
  5. write block memory driver for ADC, so waveform/FFT...are possible.
  6. TS5600 device support for ADCs/DIOs/DACs.[done]

11 Source Code:

11.1 devAiTS5500.c

/* devAiTS5500.c */

/*

 *   Technologic TS5500 analog digital converter PC104 form factor

 *  

 *   Kernel level driver support most be loaded for the EPICS

 *   device support to work

 *

 *

 */  

/* Modification Log:

 * ---------

 *      ...

 */

#include        <stdlib.h>

#include        <stdio.h>

#include        <string.h>

#include        <unistd.h>

#include        <fcntl.h>

#include        <sys/ioctl.h>

#include        "alarm.h"

#include        "cvtTable.h"

#include        "dbDefs.h"

#include        "dbAccess.h"

#include        "recSup.h"

#include        "devSup.h"

#include        "link.h"

#include        "dbScan.h"

#include        "epicsExport.h"

#include        "aiRecord.h"

#include        "a2d_driver.h"

static unsigned getbit(unsigned, int);

static long init_record();

static long read_ai();

static long special_linconv();

struct {

  long          number;

  DEVSUPFUN     report;

  DEVSUPFUN     init;

  DEVSUPFUN     init_record;

  DEVSUPFUN     get_ioint_info;

  DEVSUPFUN     read_ai;

  DEVSUPFUN       special_linconv;

} devAiTS5500={

  6,

  NULL,

  NULL,

  init_record,

  NULL,

  read_ai,

  special_linconv};

epicsExportAddress(dset,devAiTS5500);

static long init_record(pai)

     struct aiRecord    *pai;

{

  unsigned short value;

  struct vmeio *pvmeio;

  long status;

  char dev[50];

  int fd;

  int range;

  int card;

  int channel;

  int command;

  /* 

   *  ai.inp must be an VME_IO, hijack VME_IO link field for ISA bus

   *  on PC104 card [card/channel/config], card=0 

   */

  switch (pai->inp.type) {

  case (VME_IO) :

    printf("devAiTS5500: inp.type correctly set to VME_IO\n");

    break;

  default :

    errlogPrintf("devAiTS5500 (init_record) Illegal INP field, should be VME_IO\n");

    return(S_db_badField);

  }

  /* set linear conversion slope, this does not appear to be working*/

  /* open the I/O device, get card, channel, and range  from

   * inp field */

  pvmeio = (struct vmeio *)&(pai->inp.value);

  sprintf(dev,"/dev/AtoD/%i",pvmeio->signal);

  fd = open (dev, O_RDWR);

  if(fd < 0) {

    errlogPrintf("devAiTS5500 (init_record) error, unable to open device:%s\:\n", dev);

    return(fd);

  } else {

    /* set range/polarity  bit0=0 ->high range  bit0=1 -> low range

                           bit1=0 ->bipolar     bit1=1 -> unipolar */

    range = atoi(pvmeio->parm);

    if (        !(getbit(range,0))  && !(getbit(range,1))) {

      command = (A2D_BIPOLAR | A2D_RANGE2);

    } else if (  (getbit(range,0))  && !(getbit(range,1))) {

      command = (A2D_BIPOLAR | A2D_RANGE1);

    } else if ( !(getbit(range,0))  &&  (getbit(range,1))) {

      command = (A2D_UNIPOLAR | A2D_RANGE2);

    } else if (  (getbit(range,0))  &&  (getbit(range,1))) {

      command = (A2D_UNIPOLAR | A2D_RANGE1);

    } else {

      printf("devAiTS5500 %i  NOT A KNOWN RANGE/POLARITY  %i %i\n",

             pvmeio->signal, command, range);

      command = (A2D_BIPOLAR | A2D_RANGE2);

    }

    printf("\nrange: %i command %i  bit0  %i  bit1 %i\n", 

           range, command, getbit(range,0), getbit(range,1));

    errlogPrintf("devAiTS5500: setting card.chan: %i\.%i to type: %i\n",

           pvmeio->card,pvmeio->signal,range);

    ioctl(fd, TSA2D_CONFIG, command);

    /* set the slope based on range/polarity */

    if (command & A2D_RANGE2) {

      if (command & A2D_BIPOLAR) { 

        /* +/- 10V */

        pai->eslo = 20./4096;

      } else {

        /* 0->10V */

        pai->eslo = 10./4096;

      }

    } else {

      if (command & A2D_BIPOLAR) {

        /* +/- 5V  */

        pai->eslo = 10./4096;

      } else {

        /*  0-> +5V */

        pai->eslo = 5./4096;

      }

    }

    printf("devAiTS5500 %i slope %f %i\n",

           pvmeio->signal, pai->eslo, command);

      

  }

  close(fd);

  return(0);

}

static long read_ai(pai)

     struct aiRecord    *pai;

{

  struct vmeio *pvmeio;

  int fd;

  char dev[50];

  short int datavalue;

  short int status;

  short int ret_status;

  pvmeio = (struct vmeio *)&(pai->inp.value);

  ret_status = -1;

  sprintf(dev, "/dev/AtoD/%i",pvmeio->signal);

  /*  printf("devAiTS5500: read_ai: opening device %s\n", dev); */

  fd = open (dev, O_RDWR);

  if(fd > 0) {

    status = write(fd, "trigger", sizeof("trigger"));

    if (status < 0) {

      errlogPrintf("devAiTS5500: write error: returned %d\n", status);

    } else {

      status = read (fd, &datavalue, sizeof(short int));

      if (datavalue < 0) {

        datavalue - (-1*datavalue);

      }

      pai->rval = datavalue;

      /*      printf("devAiTS5500: chan: %i  reads %i  %i \n", pvmeio->signal, datavalue, pai->rval); */

      ret_status = 0;

    }

  } else {

    errlogPrintf("devAiTS5500 (init_record) TS5500_driver error, unable to open device\n");

  }

  close(fd);

  return(ret_status);

}

  

static long special_linconv(pai,after)

    struct aiRecord     *pai;

    int after;

{

    if(!after) return(0);

    /* set linear conversion slope*/

    pai->eslo = (pai->eguf - pai->egul)/32768.0;

    errlogPrintf("devAiTS5500 slope %f\n",pai->eslo);

    return(0);

}

11.2 devBiTS5500.c

/* devBiTS5500.c */

/*

 *  dev support for DIO on TS5500 card

 *  default it to set the first four lines as output

 *  the rest are inputs.

 *

 *  No use is made of the LCD port which can provide

 *  addition DIO if needed.

 *

 *  This device supports makes direct access of IO ports

 *  and must be run as root.   A better alternative would

 *  be to write char driver, so the epics device

 *  support could work in user space. 

 */  

/* Modification Log:

 * ---------

 *      ...

 */

#include        <stdlib.h>

#include        <stdio.h>

#include        <string.h>

#include        <unistd.h>

#include        <fcntl.h>

#include        <sys/io.h>

#include        <sys/ioctl.h>

#include        "alarm.h"

#include        "cvtTable.h"

#include        "dbDefs.h"

#include        "dbAccess.h"

#include        "recSup.h"

#include        "devSup.h"

#include        "link.h"

#include        "dbScan.h"

#include        "epicsExport.h"

#include        "biRecord.h"

static long init_record();

static long read_bi();

unsigned getbit(unsigned, int);

struct {

  long          number;

  DEVSUPFUN     report;

  DEVSUPFUN     init;

  DEVSUPFUN     init_record;

  DEVSUPFUN     get_ioint_info;

  DEVSUPFUN     read_bi;

} devBiTS5500={

  5,

  NULL,

  NULL,

  init_record,

  NULL,

  read_bi

};

epicsExportAddress(dset,devBiTS5500);

static long init_record(pbi)

     struct biRecord    *pbi;

{

  struct vmeio *pvmeio;

  int base_addr = 0x7A;

  int addr;

  /* 

   *  bi.inp must be an VME_IO, hijack VME_IO link field for ISA bus

   *  on PC104 card [card/channel/config]

   */

  switch (pbi->inp.type) {

  case (VME_IO) :

    printf("devBiTS5500: inp.type correctly set to VME_IO\n");

    break;

  default :

    errlogPrintf("devBiTS5500 (init_record) Illegal INP field, should be VME_IO\n");

    return(S_db_badField);

  }

  /* only need to do this once, does it hurt to do it for each record? */

  pvmeio = (struct vmeio *)&(pbi->inp.value);

  addr = base_addr + 3*(pvmeio->card - 1);

  /* configure the ports on DIO1/2: 8->11 output  rest input */

  if (ioperm(addr,1,1)<0){

    printf("Error\n");

    return(-1);

  }

  /* set pins8 to 11 to outputs*/

  printf("devBiTS5500: configuring port 0x%x\n",addr);

  outb(0x20,addr);

  /* release the port and return */

  ioperm(addr,1,0);

  return(0);

}

static long read_bi(pbi)

     struct biRecord    *pbi;

{

  struct vmeio *pvmeio;

  int bit;

  short int ret_status;

  int base_addr=0x7B;

  int addr;

  int cnt=0;

  ret_status = -1;

  pvmeio = (struct vmeio *)&(pbi->inp.value);

  

  bit = pvmeio->signal % 8;

  addr = base_addr + 3*(pvmeio->card - 1) + pvmeio->signal/8;

  if (ioperm(addr,1,1)<0){

    printf("Error cannot access DIO port/channel %i %i addr: 0x%x\n",

           pvmeio->card, pvmeio->signal, addr);

  } else {

    ret_status = 0;

    pbi->rval = getbit(inb(addr), bit);

  }

  ioperm(addr,1,0);

  return(ret_status);

}

  

11.3 devBoTS5500.c

/* devBoTS5500.c */

/*

 *  dev support for DIO on TS5500 card

 *  default it to set the first four lines as output

 *  the rest are inputs.

 *

 *  No use is made of the LCD port which can provide

 *  addition DIO if needed.

 *

 *  This device supports makes direct access of IO ports

 *  and must be run as root.   A better alternative would

 *  be to write char driver, so the epics device

 *  support could work in user space. 

 */  

/* Modification Log:

 * ---------

 *      ...

 */

#include        <stdlib.h>

#include        <stdio.h>

#include        <string.h>

#include        <unistd.h>

#include        <fcntl.h>

#include        <sys/io.h>

#include        <sys/ioctl.h>

#include        "alarm.h"

#include        "cvtTable.h"

#include        "dbDefs.h"

#include        "dbAccess.h"

#include        "recSup.h"

#include        "devSup.h"

#include        "link.h"

#include        "dbScan.h"

#include        "epicsExport.h"

#include        "boRecord.h"

static long init_record();

static long write_bo();

unsigned setbit(unsigned, int, unsigned );

struct {

  long          number;

  DEVSUPFUN     report;

  DEVSUPFUN     init;

  DEVSUPFUN     init_record;

  DEVSUPFUN     get_ioint_info;

  DEVSUPFUN     write_bo;

} devBoTS5500={

  5,

  NULL,

  NULL,

  init_record,

  NULL,

  write_bo

};

epicsExportAddress(dset,devBoTS5500);

static long init_record(pbo)

     struct boRecord    *pbo;

{

  struct vmeio *pvmeio;

  int base_addr = 0x7A;

  int addr;

  /* 

   *  bo.inp must be an VME_IO, hijack VME_IO link field for ISA bus

   *  on PC104 card [card/channel/config]

   */

  switch (pbo->out.type) {

  case (VME_IO) :

    printf("devBiTS5500: inp.type correctly set to VME_IO\n");

    break;

  default :

    errlogPrintf("devBiTS5500 (init_record) Illegal INP field, should be VME_IO\n");

    return(S_db_badField);

  }

  /* only need to do this once, does it hurt to do it for each record? */

  pvmeio = (struct vmeio *)&(pbo->out.value);

  addr = base_addr + 3*(pvmeio->card - 1);

  /* configure the ports on DIO1/2: 8->11 output  rest input */

  if (ioperm(addr,1,1)<0){

    printf("Error\n");

    return(-1);

  }

  /* set pins8 to 11 to outputs*/

  printf("devBiTS5500: configuring port 0x%x\n",addr);

  outb(0x20,addr);

  /* release the port and return */

  ioperm(addr,1,0);

  return(0);

}

static long write_bo(pbo)

     struct boRecord    *pbo;

{

  struct vmeio *pvmeio;

  int bit;

  short int ret_status;

  int base_addr=0x7B;

  int addr;

  int value;

  ret_status = -1;

  pvmeio = (struct vmeio *)&(pbo->out.value);

  

  bit = pvmeio->signal % 8;

  addr = base_addr + 3*(pvmeio->card - 1) + pvmeio->signal/8;

  if (ioperm(addr,1,1)<0){

    printf("Error cannot access DIO port/channel %i %i addr: 0x%x\n",

           pvmeio->card, pvmeio->signal, addr);

  } else {

    ret_status = 0;

    /* read the port */

    value = inb(addr);

    /* overwrite the appropriate bit */

    value = setbit((unsigned) value, bit,(unsigned) pbo->rval);

    /*     pbo->rval = getbit(inb(addr), bit); */

    outb(value, addr);

  }

  ioperm(addr,1,0);

  return(ret_status);

}

  

About this document ...

EPICS on a TS5500 PC104 CPU Running Linux

This document was generated using the LaTeX2HTML translator Version 2002 (1.62)

Copyright © 1993, 1994, 1995, 1996, Nikos Drakos, Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999, Ross Moore, Mathematics Department, Macquarie University, Sydney.

The command line arguments were:
latex2html -no_subdir -split 0 -show_section_numbers /tmp/lyx_tmpdir1774156jv4F/lyx_tmpbuf0/ts5500.tex

The translation was initiated by Arne Freyberger on 2004-09-23


Footnotes

... PC1041
There is a mail list server for PC104 questions/news here at JLAB. The archive can be found at:PC104 mail archive http://www.jlab.org/ccc/mail_archives/ELECTRONICS/pc104/CURRENT/
... slot2
See the Technologic website for all the options and pricing. technologic TS5500 options http://www.embeddedx86.com/epc/ts5500-spec-h.php
... reboot3
Technically a reboot is not necessary, one just needs to restart the network via ``/etc/init.d/network restart'' and restart the epics process by killing the old one ``kill -9 ??????'' followed by ``/etc/init.d/Epics.script start''.
... yet4
The TS5500 has 38 DIO one three ports, DIO1, DIO2 and LCD. Device support has not been written for the LCD port at this time. So there are potentially 11 more DIO channels of which 2 are outputs, 1 an input and 8 can be defined as either input or output.
... SBC5
The vi editor is available on the TS5500. If you are unfamilar with the vi editor make sure you have a tutorial handy before you start editting.
... hardware6
For example a VME minicrate and CPU will cost a minimum of $5000, while the TS5500 with an enclosure and eight ADCs costs less then $500. If one adds the cost of a VME DIO card [about $1000] and VME ADC [about $1000] the savings are even greater.
... previously7
The device support for the DIO and ADC do not require state code support, for details on installing the State Notation Code [SNC] compiler see:EPICS R3.14.2 on Linux Host http://www.jlab.org/ccc/mail_archives/ELECTRONICS/pc104/CURRENT/msg00013.html
... Makefile8
This is based loosely on the structure developed and implemented by Mark Ito for the Hall-B Epics development as well as the default EPICS structure. There is still work [scripts and Makefile] that needs to be done to make this a working system fully operational and used concurrently by more than one developer.
... read/writes9
This means the EPICS application needs to run as root. A Linux char driver for the DIO lines would make the EPICS device support more straight forward. This is on the todo list.
... &10
Thanks to Mark Ito for coming up with this solution.
... environment11
For example, grab and save some data whenever there is an FSD trip.

next_inactive up previous
Arne Freyberger 2004-09-23