Writing C code for vxWorks - PowerPoint PPT Presentation

1 / 21
About This Presentation
Title:

Writing C code for vxWorks

Description:

Writing C code for vxWorks Especially sub and genSub record Contents vxWorks intro Major differences between vxWorks and Unix/Linux vxWorks Help vxWorks shell VME ... – PowerPoint PPT presentation

Number of Views:214
Avg rating:3.0/5.0
Slides: 22
Provided by: Adm947
Category:

less

Transcript and Presenter's Notes

Title: Writing C code for vxWorks


1
Writing C code for vxWorks
  • Especially sub and genSub record

2
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

3
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.

4
vxWorks help
  • Online help http//vxworks.web.psi.ch
  • Important for beginnersVxWorks Programmer's
    Guide, Chapter 2
  • All about tasks, semaphores, watchdog timers,
    interrupts
  • Always helpfulvxWorks Reference Manual
  • All vxWorks system functions
  • Run-time help Type help on the vxWorks shell.

5
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).

6
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,

7
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.

8
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

9
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

10
Subroutione record user function
  • Inputs are in fields a l (type double).
  • Output goes to val (type double).
  • int foobar (struct subRecord record)
    record-gtval record-gtval record-gta
    record-gtb return 0
  • Specify name of function in SNAM field of record.
  • record (sub, "(NAME)") field (SNAM,
    "foobar")

11
Subroutine record initialization
  • Optional init function
  • int foobar_init (subRecord record)
    record-gtval 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.

12
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.

13
Asynchronous subroutine stub
  • typedef struct SEM_ID trigger
    CALLBACK cb / whatever you need /
    asyncSubPriv
  • void asyncSubTask(struct subRecord record)
    asyncSubPriv priv record-gtdpvt / do
    calculations / callbackRequestProcessCallback
    (priv-gtcb, record-gtprio, record)
  • int asyncSubInit(struct subRecord record)
    asyncSubPriv priv malloc(sizeof(asyncSubPriv))
    taskSpawn("asyncSub",200,VX_FP_TASK,10000,(FU
    NCPTR)asyncSubTask,(int)record,0,0,0,0,0,0,0,0,0)
    priv-gttrigger semBCreate(SEM_Q_FIFO,SEM_EMP
    TY) / add error checking /
    record-gtdpvt priv return 0
  • int asyncSub(struct subRecord record)
    asyncSubPriv priv record-gtdpvt if (priv
    NULL) return ERROR if (record-gtpact)
    return 0 semGive(priv-gttrigger) return
    1

14
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"

15
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.

16
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.

17
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.

18
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.

19
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
    "hytec"
  • or require "hytec","1"
  • or require "hytec","1.4"
  • or require "hytec","1.4.2"
  • or require "hytec","test"
  • Recommended if code is used by many IOCs.

20
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

21
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
Write a Comment
User Comments (0)
About PowerShow.com