The test application for the Cogent CIF Driver for Hilscher Fieldbus CIF Cards is a C program which comes with the CIF Driver distribution. It can be run from the command line using the command dvn_test. The command-line options are as follow:
-q Interactive mode - query between steps
-i iter Repeat test this many times
-n taskname Connect to this published driver name
-p point Name of test point
(must be specified to invoke point and direct interface tests)
-b addr Base address of test block (dflt: 0)
-l len Length of test block (bytes)
(must be specified to perform block tests)
-a addr Byte offset in block of analog word to write (dflt 0)
-d addr Byte offset in block of digital word to write (dflt 4)
-s Block data words are high-low byte formatThe code for the test application is shown here.
/* **********************************************************************
*
* Filename: cif_test.c
* Description: Sample application for CIF card administrator
* - tests functionality of driver and interfaces
*
********************************************************************** */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <machdep.h>
#include <unistd.h>
#ifdef HAVE_SYS_NAME_H
#include <sys/name.h>
#endif
#ifdef HAVE_SYS_KERNEL_H
#include <sys/kernel.h>
#endif
#include <ioport.h>
#include "dr_api.h"
#include "cif_api.h"
#define MAX_DATA_SIZE 80
#define MAX_MSG_SIZE (sizeof(DR_ApBlkHdr_t) -1 + MAX_DATA_SIZE)
#define DATA_MSG_SIZE (sizeof(DR_ApBlkHdr_t) -1 + sizeof(short))
static IP_Task* AdminTask;
/* ****************************************************************************
* ToggleOutputBit
* uses direct QNX IPC messages (bypasses API) to read and then write
* a pair of bytes from/to the specified process
*/
int ToggleOutputBit(IP_Task* admin_task, int device, int buffer,
unsigned short ofs, int bit)
{
int result=0;
unsigned short *data_word;
char msg [MAX_MSG_SIZE];
DR_ApBlkHdr_t *hdr;
/* setup a message to read the specified 2 bytes from an
output buffer */
hdr = (DR_ApBlkHdr_t *) msg;
data_word = (unsigned short *)hdr->data;
hdr->cmd = DR_API_BLK_RD;
hdr->dev = device;
hdr->buffer = buffer;
hdr->buf_size = MAX_MSG_SIZE;
hdr->offset = ofs;
hdr->size = sizeof(short);
result = IP_TaskSendRaw (admin_task, msg, DATA_MSG_SIZE,
msg, MAX_MSG_SIZE);
if (result == 0)
{
if (!(result = hdr->status))
{
/* toggle the bit */
(*data_word) ^= 1<<(bit-1);
/* write it back out */
hdr->cmd = DR_API_BLK_WR;
result = IP_TaskSendRaw (admin_task, msg, DATA_MSG_SIZE, msg,
MAX_MSG_SIZE);
}
else
printf (" Administrator response: %s\n", hdr->data);
}
else
printf (" Error %d sending to administrator\n",
result);
return (result);
}
/* ****************************************************************************
* ReadBufferWord
* uses direct QNX IPC messages (bypasses API) to read
* a pair of bytes from/to the specified process
*/
int ReadBufferWord(IP_Task* admin_task, int device,
unsigned short buffer, unsigned short ofs)
{
int result=0;
unsigned short *data_word;
char msg [MAX_MSG_SIZE];
DR_ApBlkHdr_t *hdr;
/* setup a message to read the specified 2 bytes from the buffer */
hdr = (DR_ApBlkHdr_t *) msg;
data_word = (unsigned short *)hdr->data;
hdr->cmd = DR_API_BLK_RD;
hdr->dev = device;
hdr->buffer = buffer;
hdr->buf_size = MAX_MSG_SIZE;
hdr->offset = ofs;
hdr->size = 2;
result = IP_TaskSendRaw (admin_task, msg, DATA_MSG_SIZE,
msg, MAX_MSG_SIZE);
if (result == 0)
{
if (!(result = hdr->status))
{
printf (" Data at %X[%X] = %X\n", buffer, ofs, *data_word);
}
else
printf (" Administrator error %d %s\n", hdr->status, "FIXME");
}
else
printf (" Error %d sending to administrator\n",
result);
return (result);
}
void dump_data (int indent, char *data, int length, int width, int addr_ofs)
{
int i,j;
for (i=0; i<length;)
{
printf("%*s%04X: ", indent, "|", addr_ofs + i);
for (j=0; j<width && i<length; j+=2, i+=2)
printf("%02X%02X ",
(unsigned char)data[i], (unsigned char)data[i+1]);
printf("\n");
}
}
void wait_for_kybd (int single_step)
{
if (single_step)
{
printf ("Press ENTER to continue");
fflush (stdout);
getchar();
printf ("\n");
}
}
static const char USAGE[] =
"Usage: cif_test [-hq] [-n admin_name] options\n"
;
int main (int argc, char ** argv)
{
/* test parameters & command line options */
int opt;
char *taskname;
char *admin_name = "/dr/cif";
char *test_pnt = NULL;
unsigned short block_addr=0, block_length=0;
unsigned short analog_word_ofs=0, digital_word_ofs=4;
int iter = 1, swap=0, single_step = 0;
/* common vars */
int result;
char *error_str;
char data[1024];
int nargs;
char *nargv[128];
DR_ApValue_t value;
DR_ApValue_t ivalue;
unsigned short dvalue;
/*
* Extract command line parameters
*/
/* read command line options/configuration */
taskname = argv[0];
while ((opt = getopt(argc, argv, "hqn:p:b:l:a:d:si:")) != -1)
{
switch (opt)
{
case 'h':
printf("%s Test functionality of a Cogent device driver\n\n",
taskname);
printf("%s", USAGE);
printf("\nOptions:\n");
printf("-q Interactive mode - query between steps\n");
printf("-i iter Repeat test this many times\n");
printf("-n taskname Connect to this published driver name\n");
printf("-p point Name of test point\n");
printf(" (must be specified to invoke point and direct interface tests)\n");
printf("-b addr Base address of test block (dflt: %d)\n", block_addr);
printf("-l len Length of test block (bytes)\n");
printf(" (must be specified to perform block tests)\n");
printf("-a addr Byte offset in block of analog word to write (dflt %d)\n", analog_word_ofs);
printf("-d addr Byte offset in block of digital word to write (dflt %d)\n", digital_word_ofs);
printf("-s Block data words are high-low byte format\n");
exit(0);
case 'q':
single_step = 1;
printf ("Single stepping mode on\n");
break;
case 'n':
admin_name = optarg;
printf ("Administrator name set to %s\n", admin_name);
break;
case 'p':
test_pnt = optarg;
printf ("Test point %s will be used\n", test_pnt);
break;
case 'b':
block_addr = strtoul(optarg, NULL, 0);
printf ("Test block base address set to %0X\n", block_addr);
break;
case 'l':
block_length = strtoul(optarg, NULL, 0);
printf ("Test block length set to %d bytes\n", block_length);
break;
case 'a':
analog_word_ofs = strtoul(optarg, NULL, 0);
printf ("Analog Test Word located at byte %0X of test block\n",
analog_word_ofs);
break;
case 'd':
digital_word_ofs = strtoul(optarg, NULL, 0);
printf ("Digital Test Word located at byte %0X of test block\n",
digital_word_ofs);
break;
case 's':
swap = 1;
break;
case 'i':
iter = atoi(optarg);
break;
default:
fprintf(stderr, "%s", USAGE);
exit(1);
}
}
/*
* Connect to target process
*/
if (!DR_ApInitIPC (taskname, admin_name))
{
int count;
printf ("Successfully connected %s to %s\n\n", taskname, admin_name);
for (count=0; count<iter; count++)
{
/* **************************************
* test group A: command interface
************************************** */
wait_for_kybd (single_step);
printf ("\nA) Testing command interface.\n");
{
/*** test A.1 send a command to list available commands */
result = DR_ApCommand ("(apropos *)", data, 1024, &error_str);
if (result == ST_OK)
printf (" Administrator commands available:\n%s\n",data);
else
printf (" Error@ApCommand (%d, %s)\n",
result, error_str);
}
/* **************************************
* test group B: named point interface
************************************** */
wait_for_kybd (single_step);
printf ("\nB) Testing Point Interface\n");
/*** test B.1: get point names */
{
int j, type, enabled, readable, writeable;
int device, buffer;
unsigned short offset, bit;
char address[16];
nargs = 0;
result = DR_ApListPoints (NULL, &nargs, nargv, 128,
data, 1024, &error_str);
printf (" Listing points available:\n");
for (j = 1; j<nargs; j++)
{
/*** test B.2: read specified point values */
result = DR_ApReadPoint(nargv[j], &type, &value,
&error_str);
if (result == ST_OK)
{
printf (" Pnt: %s ", nargv[j]);
switch(type)
{
case DR_API_DOUBLE_TYPE:
printf ("(real) = %f\n", value.d);
break;
case DR_API_INT32_TYPE:
printf ("(int) = %d\n", value.i);
break;
case DR_API_INT16_TYPE:
printf ("(short) = %d\n", value.s);
break;
case DR_API_BIT_TYPE:
printf ("(bit) = %1X\n", value.s);
break;
default:
printf ("(%d) = %X\n", type, value.i);
}
}
else
{
printf (" Error: %s value not available\n",
nargv[j]);
// printf (" Error@ListPoints:%s (%d, %s): \n",
// nargv[j], result, error_str);
}
}
if (test_pnt)
{
wait_for_kybd (single_step);
/*** test B.3: describe a specified point */
printf (" Describing point %s: \n", test_pnt);
result = DR_ApDescribePoint (test_pnt, &type, &enabled,
&readable, &writeable,
address, sizeof(address),
&error_str);
if (result == ST_OK)
{
printf (" Point %s: type %d, %s%s, addr: %s\n",
test_pnt, type, (readable?"R":""),
(writeable?"W":""), address);
result = DR_ApPointBufAddress (test_pnt, &device,
&buffer, &offset, &bit,
&error_str);
if (result == ST_OK)
{
printf (" Maps to: device %d, buffer %d, offset: %d",
device, buffer, offset);
if (type == DR_API_BIT_TYPE)
printf (", bit: %d", bit);
printf ("\n");
}
else
printf (" Error@PointBufAddress (%d, %s)\n",
result, error_str);
}
else
printf (" Error@DescribePoint (%d, %s)\n",
result, error_str);
/*** test B.4: twiddle specified point value */
wait_for_kybd (single_step);
printf (" Activating %s\n", test_pnt);
ivalue.s = 1;
result = DR_ApWritePoint (test_pnt, DR_API_BIT_TYPE,
&ivalue, &error_str);
if (result == ST_OK)
{
delay (1000);
printf (" Deactivating %s\n", test_pnt);
ivalue.s = 0;
result = DR_ApWritePoint (test_pnt, DR_API_BIT_TYPE,
&ivalue, &error_str);
}
if (result != ST_OK)
printf (" Error@WritePoint (%d, %s)\n",
result, error_str);
}
}
/* ********************************************
* test group C: binary block data transfer
******************************************** */
wait_for_kybd (single_step);
printf ("\nC) Testing Block interface.\n");
{
int num_blks = 0;
int i, j, n_attr;
unsigned short buf_size[4];
DR_ApSegAttributes_t seg_attr[4][32];
/*** test C.1: list buffer info */
result = DR_ApListBuffers (0, 4, &num_blks, buf_size,
&error_str);
if (result == ST_OK)
{
printf (" Device 0 has %d buffers with the following sizes:\n",
num_blks);
for (i=0; i<num_blks; i++)
printf (" Buffer %d: %d bytes.\n",
i, buf_size[i]);
printf ("\n");
}
else
printf (" Error@ListBuffers (%d,%s)\n",
result, error_str);
/*** test C.2 list buffer segment attributes */
for (i=0; i<num_blks; i++)
{
result = DR_ApDescribeBuffer (0, i, 0, 32, &n_attr,
&(seg_attr[i][0]),
&error_str);
if (result == ST_OK)
{
if (n_attr == 0)
printf (" Buffer %d has not defined any segments.\n", i);
else
{
printf (" Buffer %d has defined the following segments:\n", i);
for (j=0; j<n_attr; j++)
{
printf (" Buffer %d, segment %d:",
(seg_attr[i][j].buf_id), j);
printf (" %s%s%s",
(seg_attr[i][j].readable?"reads":""),
((seg_attr[i][j].readable &&
seg_attr[i][j].writeable) ? " and ":""),
(seg_attr[i][j].writeable?"writes":""));
printf (" %s data",
((DR_API_BIT_TYPE == seg_attr[i][j].type)
?"digital":
((DR_API_INT16_TYPE == seg_attr[i][j].type)
? "analog" : "unknown type")) );
printf (" from offset %d with length %d bytes\n",
seg_attr[i][j].offset,
seg_attr[i][j].size);
}
}
}
else
printf (" Error@DescribeBuffer (%d,%s)\n",
result, error_str);
}
if (num_blks > 0 && n_attr > 0)
{
printf (" Digital Inputs (bit) are available from the following segments:\n");
for (i=0; i<num_blks; i++)
{
for (j=0; j<n_attr; j++)
{
if (seg_attr[i][j].readable &&
seg_attr[i][j].type==DR_API_BIT_TYPE)
{
printf(" buffer %d, from offset %d for %d bytes\n",
seg_attr[i][j].buf_id,
seg_attr[i][j].offset,
seg_attr[i][j].size);
}
}
}
printf (" Analog Outputs are available from the following segments:\n");
for (i=0; i<num_blks; i++)
{
for (j=0; j<n_attr; j++)
{
if (seg_attr[i][j].writeable &&
seg_attr[i][j].type==DR_API_INT16_TYPE)
{
printf(" buffer %d, from offset %d for %d bytes\n",
seg_attr[i][j].buf_id,
seg_attr[i][j].offset,
seg_attr[i][j].size);
}
}
}
printf ("\n");
}
}
if (block_length > 0)
{
/*** test C.3: read data blocks */
wait_for_kybd (single_step);
DR_ApUpdateBuffers ();
printf (" Reading input block: device %d, buffer %d, offset %d, length %d bytes \n",
0, 1, block_addr, block_length);
result = DR_ApReadBlock (0, 1, block_addr, block_length,
data, &error_str);
if (result == ST_OK)
dump_data (6, data, block_length, 16, block_addr);
else
printf (" Error@ReadBlock.input (%d,%s)\n",
result, error_str);
wait_for_kybd (single_step);
printf (" Reading output block: device %d, buffer %d, offset %d, length %d bytes \n",
0, 0, block_addr, block_length);
result = DR_ApReadBlock (0, 0, block_addr, block_length,
data, &error_str);
if (result == ST_OK)
dump_data (6, data, block_length, 16, block_addr);
else
printf (" Error@ReadBlock.output (%d,%s)\n",
result, error_str);
/*** test C.4: write data blocks */
wait_for_kybd (single_step);
{
int i, j, a_incr = 100;
unsigned short blk_addr_a = block_addr + analog_word_ofs;
unsigned short blk_addr_d = block_addr + digital_word_ofs;
printf (" Writing to output block: "
"device %d, buffer %d, offset %d, length %d bytes \n",
0, 0, block_addr, block_length);
printf (" incrementing word at block offset 0x%02X in steps of %d)\n",
blk_addr_a, a_incr);
*(short *)&data[blk_addr_a] = 0;
for (i=0; i<=100 && result==ST_OK; i++)
{
if (swap)
{
/* swab(src,dst,n) */
swab (&(data[blk_addr_a]), (char *)&ivalue, 2);
ivalue.s += a_incr;
swab ((char *)&ivalue, &(data[blk_addr_a]), 2);
}
else
{
/* memcpy(dst,src,n) */
memcpy ((char *)&ivalue, &(data[blk_addr_a]), 2);
ivalue.s += a_incr;
memcpy (&(data[blk_addr_a]), (char *)&ivalue, 2);
}
printf ("\r %+06d ", ivalue.s);
for (j=0; j<block_length; j+=2)
printf("%02X%02X ",
(unsigned char)data[block_addr + j],
(unsigned char)data[block_addr + j+1]);
fflush (stdout);
result = DR_ApWriteBlock (0, 0, block_addr, block_length,
data, &error_str);
if (result != ST_OK)
printf (" Error@WriteBlock (%d,%s)\n",
result, error_str);
DR_ApUpdateBuffers ();
delay (50);
}
printf ("\n");
*(short *)&data[blk_addr_a] = 0;
printf (" cycling bit through byte at block byte offset 0x%02X.\n",
blk_addr_d);
for (i=0; i<=8 && result==ST_OK; i++)
{
dvalue = data[blk_addr_d] & 0x00FF;
if (dvalue == 0)
dvalue = 1;
else
dvalue <<= 1;
data[blk_addr_d] = dvalue;
printf ("\r %04X ", dvalue);
for (j=0; j<block_length; j+=2)
printf("%02X%02X ",
(unsigned char)data[block_addr + j],
(unsigned char)data[block_addr + j+1]);
fflush (stdout);
result = DR_ApWriteBlock (0, 0, block_addr, block_length,
data, &error_str);
if (result != ST_OK)
printf (" Error@WriteBlock (%d,%s)\n",
result, error_str);
DR_ApUpdateBuffers ();
delay (500);
}
printf ("\n");
/* clear output digitals */
data[blk_addr_d] = 0;
result = DR_ApWriteBlock (0, 0, block_addr, block_length,
data, &error_str);
DR_ApUpdateBuffers ();
}
}
else
printf (" Block data read/write test skipped (block_length = 0)\n");
/* ********************************************
* test group D: control and status
******************************************** */
wait_for_kybd (single_step);
printf ("\nD) Testing Control & Status interface.\n");
{
int i;
cif_ApParms_t control;
cif_ApState_t status;
printf (" Reading Protocol Parameters:\n");
result = DR_ApReadControl (0, 2, 0, sizeof (cif_ApParms_t),
&control, &error_str);
if (result != ST_OK)
printf (" Error@ReadControl (%d,%s)\n",
result, error_str);
else
{
printf (" Mode = %s (%X)\n",
IOMODE_STR(control.Mode), control.Mode);
printf (" Storage format = %s (%d)\n",
FORMAT_STR(control.Format), control.Format);
printf (" Watchdog Time = %d\n", control.WatchdogTime);
}
printf (" Reading Status:\n");
if ((result = DR_ApReadStatus (0, 2, 0, sizeof (cif_ApState_t),
&status, &error_str)))
printf (" Error@ReadStatus (%d,%s)\n",
result, error_str);
else
{
printf (" GlobalState = %s, %s, %s\n",
(status.GlobalBits & STATE_GLOBAL_CTRL ?
"Parm error" : "Parms OK"),
(status.GlobalBits & STATE_GLOBAL_ACLR ?
"AutoClear/Slave error" :
"Mode/Slaves OK"),
(status.GlobalBits & STATE_GLOBAL_NDATA ?
"Slave Fatal error" : "Slaves OK"));
printf (" DPMState = %s (%2.2X)\n",
STATE_STR(status.DPMState),
status.DPMState);
printf (" Error status: (%d, %d)\n",
status.ErrorRemoteAddr, status.ErrorEvent);
printf (" Slaves state: ");
for (i=0; i<16; i++)
printf ("%2.2X", (unsigned char) status.SlaveState[i]);
printf ("\n");
printf (" Slaves diagnostic bits: ");
for (i=0; i<16; i++)
printf ("%2.2X", (unsigned char) status.SlaveDiags[i]);
printf ("\n");
}
}
/* ********************************************
* test group E: direct interface
******************************************** */
wait_for_kybd (single_step);
printf ("\nE) Testing Direct interface: toggle test point.\n");
if (test_pnt)
{
int type, enabled, readable, writeable;
int device, buffer;
unsigned short offset, bit;
result = DR_ApDescribePoint (test_pnt, &type, &enabled,
&readable, &writeable,
NULL, 0, &error_str);
result = DR_ApPointBufAddress (test_pnt, &device,
&buffer, &offset, &bit,
&error_str);
if (writeable && type==DR_API_BIT_TYPE)
{
AdminTask = IP_TaskNew();
if (IP_NserveLookup(admin_name, AdminTask) == -1)
{
IP_TaskDestroy (AdminTask);
AdminTask = NULL;
}
if (AdminTask)
{
printf (" Toggle bit of %s at %d:%d:%d:%d\n",
test_pnt, 0, 0, offset, bit);
/* remember: named point addresses are in word offsets;
direct and block level interfaces need byte offsets
*/
offset *= 2;
ToggleOutputBit(AdminTask, device, buffer, offset,bit);
DR_ApUpdateBuffers();
delay(1000);
ToggleOutputBit(AdminTask, device, buffer, offset,bit);
DR_ApUpdateBuffers();
IP_TaskDestroy (AdminTask);
AdminTask = NULL;
}
else
printf (" Could not locate administrator %s\n",
admin_name);
}
else
printf (" Select another point that is of type digital and writeable \n");
delay (1000);
}
else
printf (" Test skipped - no test point specified\n");
}
DR_ApCloseIPC();
}
else
printf ("Failed to connect %s to %s\n", argv[0], argv[1]);
return (0);
}
Copyright © 1995-2006 by Cogent Real-Time Systems, Inc. All rights reserved.