Commit 073f55fa authored by Alessandro Rubini's avatar Alessandro Rubini

tools: new wr-dio-pps trivial command as a C language API demo

Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent 62c17953
......@@ -718,12 +718,14 @@ and associated @i{printk} -- the time is usually 5 microseconds for me:
@end example
@c ==========================================================================
@node WR-NIC User Tool
@section WR-NIC User Tool
@node WR-NIC Comamnd Tool
@section WR-NIC Command Tool
In the @file{tools/} subdirectory of this project, you find the
@file{wr-dio-cmd} program, which is a command-line interface to the
@i{ioctl} command to simplify initial access to the DIO device.
@i{ioctl} command to simplify initial access to the DIO device. Other
@code{wr-dio-} tools are provided (and described below) but this is
the most generic one.
Please note that neither timestamping nor pulse generation work
if the WR core is not running or has an invalid time: it must either be
......@@ -836,6 +838,27 @@ Example uses of the tool follow:
wr-dio-cmd wr0 mode Ii--0
@end example
@c ==========================================================================
@node WR-NIC Pulse per Second
@section WR-NIC Pulse per Second
To better show how to write your own application with the SPEC driver
and the @i{simple DIO} mezzanine card, this package includes
@file{wr-dio-pps}, which features a very small and readable source
file.
The program just fires a 1ms-long @i{pps} pulse on one of the output
channels. The NIC defaults to @i{wr0} but can specify a different one;
the channel number is a mandatory argument.
@example
# run pps on channel 2 of the default SPEC card
./wr-nic-pps 2
# run pps on channel 0 of the "second" card
./wr-nic-pps wr1 0
@end example
@c ==========================================================================
@node The Future of WR-NIC
@section The Future of WR-NIC
......
......@@ -4,3 +4,4 @@ specmem
spec-fwloader
spec-vuart
wr-dio-cmd
wr-dio-pps
......@@ -6,7 +6,7 @@ LIB = libspec.a
LIBOBJ = speclib.o loader-ll.o
PROGS = spec-cl spec-fwloader spec-vuart specmem
PROGS += wr-dio-cmd
PROGS += wr-dio-cmd wr-dio-pps
all: $(LIB) $(PROGS)
......
/*
* Copyright (C) 2012 CERN (www.cern.ch)
* Author: Alessandro Rubini <rubini@gnudd.com>
*
* Released to the public domain as sample code to be customized.
*
* This work is part of the White Rabbit project, a research effort led
* by CERN, the European Institute for Nuclear Research.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/if_ether.h>
#include <net/if.h>
#include <netpacket/packet.h>
#include "wr_nic/wr-nic.h"
#include "wr-dio.h"
/* This takes two arguments: interface name and channel number */
int main(int argc, char **argv)
{
struct wr_dio_cmd _cmd;
struct wr_dio_cmd *cmd = &_cmd;
struct ifreq ifr;
char *prgname = argv[0];
char *ifname = "wr0";
int sock, ch, charg = 1;
char c;
if (argc < 2 || argc > 3) {
fprintf(stderr, "%s: Use \"%s [<ifname>] <channel>\"\n",
prgname, prgname);
exit(1);
}
if (argc == 3) {
ifname = argv[1];
charg++;
}
if (sscanf(argv[charg], "%i%c", &ch, &c) != 1) {
fprintf(stderr, "%s: Not a channel number \"%s\"\n",
prgname, argv[charg]);
exit(1);
}
if (ch < 0 || ch > 4) {
fprintf(stderr, "%s: Out of range channel number \"%s\"\n",
prgname, argv[charg]);
exit(1);
}
fprintf(stderr, "%s: Using interface \"%s\" and channel %i for "
"pps output\n", prgname, ifname, ch);
/* The following is standard stuff to access wr-nic */
sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sock < 0) {
fprintf(stderr, "%s: socket(): %s\n",
prgname, strerror(errno));
exit(1);
}
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
if (ioctl(sock, PRIV_MEZZANINE_ID, &ifr) < 0
/* EAGAIN is special: it means we have no ID to check yet */
&& errno != EAGAIN) {
fprintf(stderr, "%s: ioctl(PRIV_MEZZANINE_ID(%s)): %s\n",
prgname, ifname, strerror(errno));
}
/* Fill the command structure */
memset(cmd, 0, sizeof(*cmd));
cmd->command = WR_DIO_CMD_PULSE;
cmd->flags = WR_DIO_F_REL | WR_DIO_F_LOOP;
cmd->value = -1;
cmd->channel = ch;
cmd->t[0].tv_sec = 2;
cmd->t[1].tv_nsec = 1000 * 1000; /* 1ms */
cmd->t[2].tv_sec = 1;
/* Give it to the driver and we are done */
ifr.ifr_data = (void *)cmd;
if (ioctl(sock, PRIV_MEZZANINE_CMD, &ifr) < 0) {
fprintf(stderr, "%s: ioctl(PRIV_MEZZANINE_CMD(%s)): %s\n",
prgname, ifname, strerror(errno));
exit(1);
}
exit(0);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment