Writing C code for vxWorks

Download Report

Transcript Writing C code for vxWorks

Writing C code for vxWorks
Especially sub and genSub record
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
Contents
■ vxWorks intro
►Major differences between vxWorks and Unix/Linux
►vxWorks Help
►vxWorks shell
►VME access
■ Calling C code from EPICS
►Subrouting records sub and genSub
■ Compiling C code for vxWorks
►driver.makefile
► require
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
Major differences between vxWorks and Unix/Linux
■ vxWorks has no programs but many threads (called "tasks").
►vxWorks has no main function.
►Every global (non static) function can be called from the shell.
■ Every global function or variable is global to the whole IOC.
►Global variables are EVIL!
■ Every function has unlimited access to every memory location.
►Every other global function and variable can be accessed.
►Every VME bus location can be accessed.
►Writing to NULL pointers corrupts the interrupt table.
►Overruning stack or allocated memory crashes the IOC.
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
vxWorks help
■ Online help: http://vxworks.web.psi.ch
►Important for beginners:
VxWorks Programmer's Guide, Chapter 2
● All about tasks, semaphores, watchdog timers, interrupts
►Always helpful:
vxWorks Reference Manual
● All vxWorks system functions
■ Run-time help: Type help on the vxWorks shell.
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
Accessing the vxWorks shell at SLS
■ Type rmc
iocname, e.g. rmc MTEST-VME-T1.
►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.
►Serial line settings: 9600 baud, 8N1, no hardware handshake
■ On Windows use hyperterm (but that is buggy).
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
Calling functions from the vxWorks shell
■ Don't 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 does not work.
►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, arg1, …
►repeatedly: repeat n, function, arg1, …
►periodically: period seconds, function, arg1, …
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
Accessing VME memory
■ VME memory is mapped to local address space.
►16 kB A16
►64 MB A24
►1 GB A32 (of 4 GB total A32 space)
■ To see mapping, type: vmeMapShow
►Mapping may change between vxWorks versions or boards.
■ To use mapping in C code, use sysBusToLocalAdrs.
■ Writing to VME is pipelined.
►When write instruction has finished, the data has not necessarily
reached the VME board. Read back if necessary.
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
Calling C code from EPICS
■ Device drivers
►Used by many record types via DTYP and INP or OUT fields.
►Some knowledge about EPICS drivers needed.
►Can only handle one record at a time.
■ Subroutine records sub and genSub
►Record calls C function by name which has access to record fields.
►sub: 12 double inputs, 1 double output
►genSub: 21 arbitrary inputs, 21 arbitrary outputs (including arrays)
■ State Notation Language
►Special C-like code for state machines
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
Subroutine record sub
■ 12 input links INPA … INPL
■ Input is copied into input fields A … L (type double)
►Either use input link or write directly to input field.
■ User function reads and A … L and writes result to VAL.
■ SNAM field contains function name.
■ INAM field contains optional init function name.
■ Functions have access to all record fields but field names are
lower case: a … l, val
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
Subroutione record user function
■ Inputs are in fields a … l (type double).
■ Output goes to val (type double).
int foobar (struct subRecord* record)
{
record->val = record->val + record->a * record->b;
return 0;
}
■ Specify name of function in SNAM field of record.
record (sub, "$(NAME)")
{
field (SNAM, "foobar")
}
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
Subroutine record initialization
■ Optional init function
int foobar_init (subRecord* record)
{
record->val = 1.0;
return 0;
}
■ Specify init function name in INAM field.
record (sub, "$(NAME)")
{
field (SNAM, "foobar")
field (INAM, "foobar_init")
}
■ Init function runs once at boot time.
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
Advanced: Asyncronous subroutine record
■ If function takes long time to complete...
►run calculation in separate task.
● Setup task in init function.
● Store data for inter task communication in dpvt field.
►trigger task from record function.
►return 1 from record function.
►re-process record when calculation completes.
● Use callbackRequestProcessCallback.
● This time, pact field is 1.
►return 0 from record function.
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
Asynchronous subroutine stub
typedef struct {
SEM_ID trigger;
CALLBACK cb;
/* whatever you need */
} asyncSubPriv;
void asyncSubTask(struct subRecord* record)
{
asyncSubPriv* priv = record->dpvt;
/* do calculations */
callbackRequestProcessCallback(&priv->cb, record->prio, record);
}
int asyncSubInit(struct subRecord* record)
{
asyncSubPriv* priv = malloc(sizeof(asyncSubPriv));
taskSpawn("asyncSub",200,VX_FP_TASK,10000,(FUNCPTR)asyncSubTask,(int)record,0,0,0,0,0,0,0,0,0);
priv->trigger = semBCreate(SEM_Q_FIFO,SEM_EMPTY);
/* add error checking */
record->dpvt = priv;
return 0;
}
int asyncSub(struct subRecord* record)
{
asyncSubPriv* priv = record->dpvt;
if (priv == NULL) return ERROR;
if (record->pact) return 0;
semGive(priv->trigger);
return 1;
}
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
General subroutine record genSub
■ All inputs and outputs are arrays of user defined type.
■ Input links and fields: INPA … INPU, A … U
■ Output fields and links: VALA … VALU, OUTA … OUTU
■ Input/output data type: FTA … FTU, FTVA … FTVU
►One of CHAR, SHORT, LONG, ULONG, FLOAT, DOUBLE, …
■ Input/output element count: NOA … NOU, NOVA … NOVU
■ Set FT* and NO* fields of all used inputs and outputs.
■ SNAM and INAM fields like in sub record.
■ The genSub record must be loaded: require "SynApps"
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
General subroutine record user function
■ Input and output fields a … u, vala … valu are void*.
■ Cast to matching pointer type.
►Even if element count is 1, it is a pointer to an array of length 1.
■ Check all ft* and no* fields in init function.
►One of menuFtypeSHORT, menuFtypeDOUBLE, …
►Never access data through void* before checking 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.
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
The problem of compiling EPICS code
■ We have 2 different vxWorks versions in use.
►The compiler runs on Linux, the code is for vxWorks.
● This is called "cross compiling".
● It is much harder to debug.
►vxWorks is similar but not exactly like Unix/Linux.
■ We run EPICS on Linux (3 versions) and Windows, too.
►Windows is completely different.
■ We have 4 different EPICS versions in use.
■ We have 2 different VME boards types in use.
■ We want to run "the same" code on all systems.
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
The solution: driver.makefile
■ We have a sophisticated makefile that builds the same code
►for all EPICS versions
►for all operating system versions (except Windows at the moment)
■ The install mechanism sorts out what code to use for an IOC
►EPICS version, OS version, board type are stored in database.
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
Using driver.makefile
■ In your source directory, create a one line Makefile
include /ioc/toos/driver.makefile
■ run make
■ It "automagically" detects all source code and builds one
loadable module from it for each EPICS/OS combination.
►Detects .c .cc .C .cpp .st .stt .dbd files in directory.
■ It detects common module or local IOC project modules
►Common modules can be installed into our driver pool.
►Common modules need proper CVS tags with version numbers.
■ If this is too much magic, it can be configured in Makefile.
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
Common modules (not only drivers)
■ Are in CVS: G/DRV/modulename, e.g. G/DRV/hytec
■ Have CVS tags with versions like hytec_1_4_2
►Untagged test versions are also supported.
■ Install to driver pool with: make install
■ IOC can load from driver pool with: require
►or require
►or require
►or require
►or require
"hytec"
"hytec","1"
"hytec","1.4"
"hytec","1.4.2"
"hytec","test"
■ Recommended if code is used by many IOCs.
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
Local IOC project modules
■ Are in CVS in some IOC project directory, A/DI/project/src/
■ Don't need version tags.
■ Can't be installed to the driver pool.
■ Are installed from slsinstall together with other project files.
►Tell your project GNUmakefile to build the code in src/
ioc:
make -C src
■ Can be loaded with require "project"
■ Recommended if code is only used for one project.
►e.g. sub/genSub functions, SNL code
Advanced EPICS Training, Dirk Zimoch 2008
Writing C code for vxWorks
Using require
■ require is a SLS extension to EPICS.
■ It is used in the IOC startup script.
■ 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
■ Uses ld and dbLoadDatabase
Advanced EPICS Training, Dirk Zimoch 2008