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 format
The code for the test application is shown here.
This code requires files from the Cogent API, which can be downloaded from the Cogent web site. |
/* ********************************************************************** * * 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-2010 by Cogent Real-Time Systems, Inc. All rights reserved.