Writing C code for IOCs Advanced EPICS Training

  • Slides: 58
Download presentation
Writing C code for IOCs Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Contents ■ vx. Works intro ► Major differences between

Writing C code for IOCs Contents ■ vx. Works intro ► Major differences between vx. Works and Unix/Linux ► Using the vx. Works shell ► Programming techniques ■ Calling C code from EPICS ► Subroutine records sub and gen. Sub ► Soft device support ► State notation language ■ Compiling C code for IOCs ► Using driver. makefile and require Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Major differences between vx. Works and Unix/Linux ■ vx.

Writing C code for IOCs Major differences between vx. Works and Unix/Linux ■ vx. Works has no programs but many threads (called "tasks"). ► The whole IOC is one "program". ► Parts of the IOC (modules, libraries, threads) are not independent. ► If any part of the "program" crashes, the whole IOC does. ■ vx. Works has no users. ► Everything runs as "root". (To be exact: in kernel space) ► Everybody can do everything. ■ vx. Works is optimized for speed – not for safety. ► You can overwrite memory, stack, interrupt tables, … Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Consequences of the "one program" concept ■ All functions

Writing C code for IOCs Consequences of the "one program" concept ■ All functions exist in the same "space". ► Name clashes may appear between different modules (libraries). ► Use unique names (with prefix) for global functions! ● Wrong: config, test, read_bi ● Right: drv. Xy. Config, foo. Test, dev. Abc_read_bi ► Or make functions static. ■ vx. Works has no main function. ■ Every function (including the shell) can call any other function. ► You don’t start programs from the shell, you call functions. Dirk Zimoch 2009 ► When name clash happens, you. Advanced might. EPICS call Training, the wrong

Writing C code for IOCs Consequences of multi threading ■ Any problem in one

Writing C code for IOCs Consequences of multi threading ■ Any problem in one thread affects the whole IOC. ■ System resources are global to the whole IOC. ► Memory ► File handles ► Semaphores ■ Ending a thread does not clean up system resources. ► The programmer (that's you!) must close files, free memory, etc. ■ Global data needs protection against concurrent access. Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Boon and bane of unlimited memory access ■ Pro:

Writing C code for IOCs Boon and bane of unlimited memory access ■ Pro: Functions and threads can easily … ► exchange large amounts of data by reference (pointers). ► access any hardware register (e. g. VME bus). ■ Con: Functions and threads can easily … ► overrun allocated memory or stack size (esp. with arrays) ► overwrite system tables. (e. g. interrupt handler table at NULL) ► overwrite program code. ► modify global variables of other modules (e. g. drivers). Global variables are EVIL! Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Contents ■ vx. Works intro ► Major differences between

Writing C code for IOCs Contents ■ vx. Works intro ► Major differences between vx. Works and Unix/Linux ► Using the vx. Works shell ► Programming techniques ■ Calling C code from EPICS ► Subroutine records sub and gen. Sub ► Soft device support ► State notation language ■ Compiling C code for IOCs ► Using driver. makefile and require Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Accessing the vx. Works shell at SLS ■ Type

Writing C code for IOCs Accessing the vx. Works shell at SLS ■ Type rmc iocname, e. g. rmc MTEST-VME-T 1. ► The SLS specific command rmc stands for "remote minicom". ► It does ssh to a central server. ► It starts minicom on the server. ► The server is connected to the DEBUG port of the IOC. ■ You must be on the same network as the IOC. ■ You may need your AFS password or the slsop password. ■ If the IOC is connected to local Linux PC, use minicom. Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs vx. Works help ■ Online help: http: //vxworks. web.

Writing C code for IOCs vx. Works help ■ Online help: http: //vxworks. web. psi. ch ► Important for beginners: Vx. Works Programmer's Guide, Chapter 2 ● All about tasks, semaphores, watchdog timers, interrupts ► Always helpful: vx. Works Reference Manual ● All vx. Works system functions ■ Run-time help: Type help on the vx. Works shell. ■ Separate talk on vx. Works debugging? Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs XTEST-VME-ID 1 > help io. Help dbg. Help nfs.

Writing C code for IOCs XTEST-VME-ID 1 > help io. Help dbg. Help nfs. Help net. Help spy. Help timex. Help h i ti sp task. Spawn td ts tr d m m. Regs pc Print this list Print I/O utilities help info Print debugger help info Print nfs help info Print network help info Print task histogrammer help info Print execution timer help info [n] Print (or set) shell history [task] Summary of tasks' TCBs task Complete info on TCB for task adr, args. . . Spawn a task, pri=100, opt=0 x 19, stk=20000 name, pri, opt, stk, adr, args. . . Spawn a task Delete a task Suspend a task Resume a task [adr[, nunits[, width]]] Display memory adr[, width] Modify memory [reg[, task]] Modify a task's registers interactively [task] Return task's program counter Type <CR> to continue, Q<CR> to stop: Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Calling functions from the vx. Works shell ■ Never

Writing C code for IOCs Calling functions from the vx. Works shell ■ Never call your main function main! ► Use a specific name, the name you would give a program on Linux. ■ The shell can pass up to 10 integer or string arguments. ► float or double shell arguments don't work on PPC architectures. ► No check is done by the shell. ► Check all arguments for sanity (numeric ranges, NULL strings, …). ■ The shell can call functions in a separate task ► sp function, arg 1, … Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Examples ■ Setting or creating global variables drv. Xy.

Writing C code for IOCs Examples ■ Setting or creating global variables drv. Xy. Debug = 1 str = "This is a string" ■ Calling functions printf (“String: %s, number: %dn”, str, drv. Xy. Debug) ► Note: Outermost parentheses are optional ■ Things that do not work ► C constructs (non-functions) like: if, switch, for, while, … ► Floating point: printf “%gn”, 3. 1415 ► More than 10 parameters Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Contents ■ vx. Works intro ► Major differences between

Writing C code for IOCs Contents ■ vx. Works intro ► Major differences between vx. Works and Unix/Linux ► Using the vx. Works shell ► Programming techniques ■ Calling C code from EPICS ► Subroutine records sub and gen. Sub ► Soft device support ► State notation language ■ Compiling C code for IOCs ► Using driver. makefile and require Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Why global variables are evil (1) ■ Global variables

Writing C code for IOCs Why global variables are evil (1) ■ Global variables with the same name in different modules are the same piece of memory. ► Problem: Two different modules may mutually overwrite their values. ► Solution 1: Make variable local to one source file with static. ► Solution. Wron 2: Prefix global variable name Right with module name. /* internal g variable */ int card_count; /* internal variable */ static int card_count; /* external variable */ int debug=0; /* external variable */ int drv. Xy. Debug=0; Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Why global variables are evil (2) ■ All instances

Writing C code for IOCs Why global variables are evil (2) ■ All instances (of threads, drivers, SNL programs …) share the same global variable. ► Problem: Two instances mutually overwrite their values. ► Solution: Wrap variables in a struct, allocate one struct per instance. Wron g /* values for one card */ static char* addr; static int ivec; Right /* linked list */ struct drv. Priv { struct drv. Priv *next; char* addr; int ivec; } drv. Priv; static drv. Priv *first=NULL; Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Debug and error messages are vital ■ Fail early

Writing C code for IOCs Debug and error messages are vital ■ Fail early and loud! ■ Make messages descriptive. ► What happened where under which circumstances? ● Bad: "error read" ● Good: "drv. Xy. Read. Integer card 4 signal 2: read timeout after 5000 msec" ■ Write error and debug messages to stderr. ■ Make debug messages switchable. (perhaps multiple levels) ► global switch: int drv. Xy. Debug=0; ► message: if (drv. Xy. Debug>=2) fprintf(stderr, …); Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Be paranoid! ■ Error checking is the key to

Writing C code for IOCs Be paranoid! ■ Error checking is the key to a stable system. ► Stability is limited by the weakest point! ■ Check arguments to API functions (esp. shell functions) ► Never trust a user! Not even yourself. ■ Always check pointer arguments for validity. ► Writing to NULL overwrites the interrupt handler table! ■ Check results of system functions (malloc, fopen, …) ► System functions may fail and return NULL or ERROR. ► Using these values unchecked may crash system Advanced EPICS the Training, Dirk Zimoch 2009

Writing C code for IOCs Contents ■ vx. Works intro ► Major differences between

Writing C code for IOCs Contents ■ vx. Works intro ► Major differences between vx. Works and Unix/Linux ► Using the vx. Works shell ► Programming techniques ■ Calling C code from EPICS ► Subroutine records sub and gen. Sub ► Soft device support ► State notation language ■ Compiling C code for IOCs ► Using driver. makefile and require Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Subroutine record sub ■ 12 input links INPA …

Writing C code for IOCs Subroutine record sub ■ 12 input links INPA … INPL, 12 input fields A … L ► Record copies from links to fields before calling user function. ► Either use input link or write directly to input field. ► Input fields are all of type double. ■ User function can use A … L and writes result to VAL. ■ SNAM field contains name of user function. ■ INAM field contains name of optional init function. ■ Functions get pointer to record and have access to all fields. Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Subroutine record user function ■ Inputs are in fields

Writing C code for IOCs Subroutine record user function ■ Inputs are in fields a … l, output goes to val (all double) ■ Example: accumulate A*B to VAL #include <sub. Record. h> int sub. Accu (struct sub. Record* record) { record->val = record->val + record->a * record->b; return 0; } ■ Specify name of function in SNAM field of record (sub, "$(NAME)") { field (SNAM, "sub. Accu") field (INPA, "$(INPUT)") field (INPB, "$(SCALE)") } Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Subroutine record initialization ■ Optional init function int sub.

Writing C code for IOCs Subroutine record initialization ■ Optional init function int sub. Accu. Init (sub. Record* record) { record->val = 1. 0; return 0; } ■ Specify init function name in INAM field. record (sub, "$(NAME)") { field (SNAM, "sub. Accu") field (INAM, "sub. Accu. Init"). . . } ■ Init function runs only once at boot time. Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Advanced: Asynchronous subroutine record ■ If function takes long

Writing C code for IOCs Advanced: Asynchronous subroutine record ■ If function takes long time to complete. . . ► Run calculation in separate work thread with low priority. ● Setup thread in init function. ● Store data for inter-thread communication in dpvt field. ► Trigger work thread from record function. ► Return 1 from record function to signal: calculation not yet complete. ► Re-process record when calculation completes. ● Use callback. Request. Process. Callback. ● pact field is 0 in first run and 1 in second run. ► Return 0 from record function to signal: calculation complete. Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Asynchronous subroutine stub #include #include <sub. Record. h> <callback.

Writing C code for IOCs Asynchronous subroutine stub #include #include <sub. Record. h> <callback. h> <task. Lib. h> <sem. Lib. h> <errno. h> /* private data for record (stored in dpvt field) */ typedef struct { int status; /* error status */ double val; /* result */ SEM_ID trigger; /* trigger for work thread */ CALLBACK cb; /* callback for re-processing */ } async. Sub. Priv; void my. Async. Sub. Thread(struct sub. Record* record); int my. Async. Sub. Init(struct sub. Record* record); Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Asynchronous subroutine work thread void my. Async. Sub. Thread(struct

Writing C code for IOCs Asynchronous subroutine work thread void my. Async. Sub. Thread(struct sub. Record* record) { async. Sub. Priv* priv = record->dpvt; /* get private data */ while (1) { /* loop forever */ sem. Take(priv->trigger, WAIT_FOREVER); /* wait */ /* do calculations */ /* leave result in priv->val */ /* leave error status in priv->status */ /* re-process record */ callback. Request. Process. Callback( &priv->cb, record->prio, record); } } Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Asynchronous subroutine user function int my. Async. Sub(struct sub.

Writing C code for IOCs Asynchronous subroutine user function int my. Async. Sub(struct sub. Record* record) { async. Sub. Priv* priv = record->dpvt; /* get private data */ if (priv == NULL) { return ERROR; } /* INAM missing */ if (record->pact == 0) { /* first run */ sem. Give(priv->trigger); /* trigger work thread */ return 1; /* signal: not yet done */ } /*second run */ if (priv->status) { /* error in work thread */ return priv->status; } record->val = priv->val; /* update record */ add error return 0; /* signal: done */ } messages here Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Asynchronous subroutine init function int my. Async. Sub. Init(struct

Writing C code for IOCs Asynchronous subroutine init function int my. Async. Sub. Init(struct sub. Record* record) { int tid; SEM_ID trigger; async. Sub. Priv* priv = malloc(sizeof(async. Sub. Priv)); if (priv == NULL) { return errno; } priv->trigger = sem. BCreate(SEM_Q_FIFO, SEM_EMPTY); if (priv->trigger == NULL) { return errno; } tid = task. Spawn("async. Sub", 200, VX_FP_TASK, 10000, (FUNCPTR) my. Async. Sub. Thread, (int) record, 0, 0, 0); if (tid == ERROR) { return errno; } record->dpvt = priv; return 0; } add error messages here Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs General subroutine record gen. Sub (compared to sub) ■

Writing C code for IOCs General subroutine record gen. Sub (compared to sub) ■ All inputs and outputs are arrays of user defined type. ► Input links INPA … INPU and fields A … U ► Output fields VALA … VALU and links OUTA … OUTU ■ Input/output data types FTA … FTU, FTVA … FTVU ► One of CHAR, SHORT, LONG, ULONG, FLOAT, DOUBLE, … ■ Input/output element count NOA … NOU, NOVA … NOVU ► Always set FT* and NO* fields of all used inputs and outputs! ■ SNAM and INAM fields similar to sub record. Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs General subroutine record user function ■ Input and output

Writing C code for IOCs General subroutine record user function ■ Input and output fields a … u, vala … valu are void*. ► Fields are pointers to arrays, even if element count is 1. ► Cast void* to correct pointer type. ● This easily crashes the IOC if ft* and no* fields are wrong! ● Always check field type and size! ● Do not process if type or size is wrong. Exit with error message. ■ Danger of crashing IOC is much higher than with sub record! ■ Checking every time the record processes is expensive. Advanced EPICS Training, Dirk Zimoch 2009 ► Check only once in init function (when IOC boots)!

Writing C code for IOCs General subroutine record init function ■ Check all data

Writing C code for IOCs General subroutine record init function ■ Check all data types and element counts. ► Field types are one of menu. Ftype. SHORT, menu. Ftype. DOUBLE, … ► Print descriptive error message if check fails! ■ Initialize any other private data (buffers, etc…) ■ Assign structure to dpvt field only if all checks succeed. ► If no private data is needed, set dpvt to a dummy value. ■ Check dpvt field at start of user function. ■ Do not process if dpvt is not set. Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Contents ■ vx. Works intro ► Major differences between

Writing C code for IOCs Contents ■ vx. Works intro ► Major differences between vx. Works and Unix/Linux ► Using the vx. Works shell ► Programming techniques ■ Calling C code from EPICS ► Subroutine records sub and gen. Sub ► Soft device support ► State notation language ■ Compiling C code for IOCs ► Using driver. makefile and require Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Soft device support ■ Available for "standard" I/O records

Writing C code for IOCs Soft device support ■ Available for "standard" I/O records ► ai, bi, mbbi, waveform, … ■ Makes a new DTYP choice available ► Just like "Soft Channel" and "Raw Soft Channel" ■ Only one input (INP) and one output (VAL) ■ Examples: ► Timestamp for stringin (INP contains format string) ► File read for waveform (INP contains file name) ► FFT for waveform (INP points to other waveform) ► Integration for waveform (INP points to other waveform) Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Writing device support ■ Write record init and read

Writing C code for IOCs Writing device support ■ Write record init and read function ■ Define a global device support function table struct { long number; DEVSUPFUN report; DEVSUPFUN init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN read; } dev. Integrate. Waveform = … ■ Write dbd file to make function table the two essential functions device support table known name device(waveform, CONSTANT, dev. Integrate. Waveform, "integrate") record type Link type, CONSTANT DTYP means: "constant or link to string record" Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Example soft device support: Integrate #include <rec. Gbl. h>

Writing C code for IOCs Example soft device support: Integrate #include <rec. Gbl. h> waveform #include <dev. Sup. h> #include <alarm. h> #include <db. Access. h> #include <waveform. Record. h> long dev. Integrate. Waveform. Init(waveform. Record *record) { switch (record->inp. type) { case (PV_LINK): case (DB_LINK): case (CA_LINK): break; default: rec. Gbl. Record. Error(S_db_bad. Field, record, "dev. Integrate. Waveform (init_record) Illegal INP field"); return S_db_bad. Field; } return 0; } Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Example soft device support: Integrate long dev. Integrate. Waveform.

Writing C code for IOCs Example soft device support: Integrate long dev. Integrate. Waveform. Read(waveform. Record *record) waveform { long status, n, i; n = record->nelm; status = db. Get. Link(&record->inp, record->ftvl, record->bptr, 0, &n); if (status) { rec. Gbl. Set. Sevr(record, READ_ALARM, INVALID_ALARM); return status; } record->nord = n; switch (record->ftvl) { case DBF_DOUBLE: { double sum = 0. 0; for (i=0; i<n; i++) { sum += ((double*)(record->bptr))[i]; ((double*)(record->bptr))[i] = sum; } break; } /* case. . . */ } return 0; } Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Example soft device support: Integrate struct { waveform long

Writing C code for IOCs Example soft device support: Integrate struct { waveform long number; DEVSUPFUN report; DEVSUPFUN init_record; DEVSUPFUN get_ioint_info; DEVSUPFUN read; } dev. Integrate. Waveform = { 5, NULL, dev. Integrate. Waveform. Init, NULL, dev. Integrate. Waveform. Read }; Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Contents ■ vx. Works intro ► Major differences between

Writing C code for IOCs Contents ■ vx. Works intro ► Major differences between vx. Works and Unix/Linux ► Using the vx. Works shell ► Programming techniques ■ Calling C code from EPICS ► Subroutine records sub and gen. Sub ► Soft device support ► State notation language ■ Compiling C code for IOCs ► Using driver. makefile and require Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs State Notation Language ■ State machine implementation for EPICS

Writing C code for IOCs State Notation Language ■ State machine implementation for EPICS ► Do something when event happens ► "Events" are CA monitors (record changes) or timeout ► "Do something" can be any C-code ■ C-like syntax ► Understands many C functions and statements ► Escapes to "real" C-code for special occasions ■ Easy to use CA interface ► pv. Put, pv. Get, monitor ■ Any number of input and output records Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Using SNL start state "cold" emp>25. 3°] / cooling

Writing C code for IOCs Using SNL start state "cold" emp>25. 3°] / cooling on [temp<22°] / cooling off state "hot" program coolingswitch int cooling; assign cooling to "{DEV}: COOLING"; double temp; assign temp to "{DEV}: TEMP"; monitor temp; ss coolingswitch { state cold { when (temp>25. 3) { cooling = 1; pv. Put(cooling); } state hot { when (temp<22. 0) { cooling = 0; pv. Put(cooling); } state cold } } Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Including C-code into SNL ■ Escape single line with

Writing C code for IOCs Including C-code into SNL ■ Escape single line with %%. . . ► especially #include ■ Escape block with %{. . . }% ■ Avoid accessing "global" SNL variables from within escaped C code. ► Implementation depends on "+r" flag program calculator %%#include <math. h> %{ void my. Calc( double i 1, double i 2, double* o 1, double* o 2) { *o 1 = sin(i 1 + i 2); *o 2 = cos(i 1 – i 2); } }% Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs "Abusing" SNL for calculations start idle [new. Input] /

Writing C code for IOCs "Abusing" SNL for calculations start idle [new. Input] / my. Calc() double in 1; double in 2; double out 1; double out 2; assign in 1 to "{DEV}: INPUT 1"; assign in 2 to "{DEV}: INPUT 2"; assign out 1 to "{DEV}: OUTPUT 1"; assign out 2 to "{DEV}: OUTPUT 2"; monitor in 1; monitor in 2; evflag new. Input; sync in 1 to new. Input; sync in 2 to new. Input; ss calculator { state idle { when (ef. Test. And. Clear(new. Input)) { my. Calc(in 1, in 2, &out 1, &out 2); pv. Put(out 1); pv. Put(out 2); } state idle } } Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Contents ■ vx. Works intro ► Major differences between

Writing C code for IOCs Contents ■ vx. Works intro ► Major differences between vx. Works and Unix/Linux ► Using the vx. Works shell ► Programming techniques ■ Calling C code from EPICS ► Subroutine records sub and gen. Sub ► Soft device support ► State notation language ■ Compiling C code for IOCs ► Using driver. makefile and require Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs The problem of compiling EPICS code ■ We have

Writing C code for IOCs The problem of compiling EPICS code ■ We have many different EPICS versions in use. ► 3. 13. 2, 3. 13. 9, 3. 10, 3. 14. 8, (3. 14. 10) ■ We have different operating systems ► 2 versions of vx. Works, 3 versions of Linux, Windows ■ We have 2 different VME boards types in use. ► MVME 2300, MVME 5100 ■ Other systems ► Embedded Linux on Virtex 4, Cosylab micro. IOC, … ■ We want to run "the same" code on all systems. Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Differences between EPICS 3. 13 and 3. 14 ■

Writing C code for IOCs Differences between EPICS 3. 13 and 3. 14 ■ EPICS 3. 14 is designed to be independent of vx. Works ► Use OSI functions instead of vx. Works functions. ► Use EPICS registry instead of vx. Works symbol table. ► More complex build mechanism to build "host"-IOCs. ■ Incompatibilities between 3. 13 and 3. 14 ► New OSI functions are not available for 3. 13. ► Registry calls must be added all over the place. ● for device support, sub/gen. Sub functions, snl state machines ► Makefile uses different variable names and mechanisms. (And make is a very complicated programming language. ) Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs The solution: driver. makefile ■ It is a sophisticated

Writing C code for IOCs The solution: driver. makefile ■ It is a sophisticated Makefile that builds the same code ► for all EPICS versions (3. 13 and 3. 14) ► for all operating system versions (except Windows at the moment) ■ It builds a module that can be loaded with require ■ In many cases, it finds out what to do automatically ► No need to write a complex Makefile ► In special cases, it can be configured ■ Originally designed for drivers, device support and new record types, it can be used for sub/gen. Sub Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs The two flavours of modules ■ Global module ►

Writing C code for IOCs The two flavours of modules ■ Global module ► Commonly used code (device driver, record type, …) ► Installed into global driver pool with make install ● Can be used by everyone ● Gets version number from CVS tag ► CVS location: G/DRV/ ► Can be loaded with require ■ Local module ► Locally used code (SNL, sub/gen. Sub functions, …) ► Installed to IOC boot directory with swit ● No interference with other modules ● Does not need version numbers ► CVS location: A, X, F, P ► Can be loaded with require Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Example global module: hytec drivers ■ CVS location: G/DRV/hytec

Writing C code for IOCs Example global module: hytec drivers ■ CVS location: G/DRV/hytec ■ Needs CVS tags with versions like hytec_1_4_2 ► Untagged test versions are also supported. ■ Install to driver pool with make install ■ Can be loaded with require "hytec" ► or require "hytec", "1" "hytec", "1. 4. 2" "hytec", "test" Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Example local module: gen. Sub function ■ CVS location:

Writing C code for IOCs Example local module: gen. Sub function ■ CVS location: X/ID/GAP ► gen. Sub function file: X/ID/GAP/src/e_to_gap. c ■ Tell project GNUmakefile to build the code in src/ ioc: build swit –V build clean: make -C src $@ ■ Install to IOC with swit together with other project files. ■ Can be loaded with require "GAP" Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Using driver. makefile ■ In your source directory, create

Writing C code for IOCs Using driver. makefile ■ In your source directory, create a one line Makefile include /ioc/tools/driver. makefile ■ Running make "automagically" builds a loadable module. ► Detects all. c, . cc, . C, . cpp, . stt, and. dbd files in directory. ► Generates module name from directory name. ► Builds for all EPICS versions. ► Builds only for vx. Works by default (but can build for Linux, too). ► Finds dependencies on other modules (drivers). Advanced 3. 13 EPICS Training, Dirk Zimoch 2009 ► Levels out many differences between and 3. 14

Writing C code for IOCs Configuring driver. makefile ■ Source code list, dbd file

Writing C code for IOCs Configuring driver. makefile ■ Source code list, dbd file list ► Default is all files in current directory ► Overwrite: SOURCES += file 1. cc SOURCES += subdir/file 2. c DBDS += xxx. dbd ■ Why overwriting? ► Files are not all in the same directory as the Makefile. ► Not all files should be used. Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Configuring driver. makefile ■ Project (module) name ► Default

Writing C code for IOCs Configuring driver. makefile ■ Project (module) name ► Default name is directory name ► If directory name is src or snl, default is name of parent directory ► Overwrite: PROJECT = othername ■ Why overwriting? ► I don't like directory name. ► Directory name contains illegal characters like – or space. ● only alphanumeric plus underscore allowed Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Configuring driver. makefile ■ EPICS versions to build ►

Writing C code for IOCs Configuring driver. makefile ■ EPICS versions to build ► Default is (3. 13. 2), 3. 13. 9, 3. 10, 3. 14. 8, (3. 14. 10) ● May change over time and depends on machine ► Exclude versions: EXCLUDE_VERSIONS = 3. 14 EXCLUDE_VERSIONS = 3. 13. 2 ■ Why excluding versions? ► Code does not compile for all EPICS versions. ► Code is not necessary for all EPICS versions. Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Configuring driver. makefile ■ Operating system class ► Default

Writing C code for IOCs Configuring driver. makefile ■ Operating system class ► Default is vx. Works only (all versions) ● Reason: backward compatibility with old vx. Works depended drivers. ► Overwrite: BUILDCLASSES = Linux (only for Linux) BUILDCLASSES += Linux (for vx. Works and Linux) ■ Why overwriting? ► Module should be used on other OS than vx. Works. ● gen. Sub or SNL code for Linux IOCs Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Configuring driver. makefile ■ Header file installation ► Default

Writing C code for IOCs Configuring driver. makefile ■ Header file installation ► Default is not to install any headers ● Exception: generated header files for new record types ► Overwrite: HEADERS += file. h ■ Why overwriting? ► Module is a lower level driver on that other drivers may depend ● For example asyn or ipac ► Only important for global modules ● Local modules are not installed for use by others Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Make targets ■ make, make build ► Builds a

Writing C code for IOCs Make targets ■ make, make build ► Builds a loadable module for each EPICS/OS combination ■ make 3. 14, make 3. 13. 2 ► Builds only for certain EPICS versions ■ make install, make install. 3. 13 ► Installs global module to driver pool ■ make uninstall ► Cleanly (!) removes global module from driver pool ■ make help ► Prints some help Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Loading modules: require ■ require is an SLS extension.

Writing C code for IOCs Loading modules: require ■ require is an SLS extension. ■ It is used in the IOC startup script to load modules. ■ It checks if a module is already loaded. ► Already loaded with compatible version is OK. ► Already loaded with incompatible version stops booting. ■ It recursively solves dependencies on other modules. ■ It loads the library and dbd file and initializes the module. ► Initialize means: make functions etc, available to the shell EPICS ► Uses ld and db. Load. Database. Advanced to load the. Training, files. Dirk Zimoch 2009

Writing C code for IOCs Using require ■ require "xxx" ► Loads latest version

Writing C code for IOCs Using require ■ require "xxx" ► Loads latest version of library ● xxx. Lib, xxx. Lib. munch, libxxx. so, or xxx. dll ► Loads dbd file xxx. dbd ► 3. 14: Calls init function xxx_register. Record. Device. Driver ■ require "xxx", "2. 1" ► Loads version 2. 1 of library and dbd file (only for global modules) ● xxx. Lib-2. 1, xxx. Lib-2. 1. munch, libxxx-2. 1. so, or xxx-2. 1. dll ■ require "xxx", "test" ► Loads test (untagged) version of library and dbd file Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Driver pool location ■ Location of global module libraries:

Writing C code for IOCs Driver pool location ■ Location of global module libraries: ► $INSTBASE/ioc. Boot/<EPICS_VERSION>/<ARCH> ► /work/ioc. Boot/R 3. 10/T 2 -ppc 604 ► /psi-xfel/prod/ioc. Boot/R 3. 14. 8/SL 5 -x 86 ■ Location of dbd files: ► $INSTBASE/ioc. Boot/<EPICS_VERSION>/dbd ■ Location of headers: ► $INSTBASE/ioc. Boot/<EPICS_VERSION>/include Advanced EPICS Training, Dirk Zimoch 2009

Writing C code for IOCs Example of link system in driver pool motor. Lib

Writing C code for IOCs Example of link system in driver pool motor. Lib -> motor. Lib-6. 2. 5 motor. Lib-4 -> motor. Lib-4. 963. 0 motor. Lib-4. 74 -> motor. Lib-4. 74. 1 motor. Lib-4. 96 -> motor. Lib-4. 96. 1 motor. Lib-4. 962 -> motor. Lib-4. 962. 0 motor. Lib-4. 963 -> motor. Lib-4. 963. 0 motor. Lib-6 -> motor. Lib-6. 2. 5 motor. Lib-test Advanced EPICS Training, Dirk Zimoch 2009