Commit 0c2eba80 authored by Jorge Machado's avatar Jorge Machado

Merge branch 'dio_extension' of https://ohwr.org/project/fmc-dio-5chttla into dio_extension

parents 9ca19cac 8f3c8d57
......@@ -53,3 +53,4 @@ modules.order
# Project Specifi #
###################
wr-dio.mod*
irq-demo
\ No newline at end of file
......@@ -559,43 +559,43 @@ Example uses of the tool follow:
@example
# Pulse channel 4 for 0.1 seconds now
wr-dio-cmd /dev/fmc-dio-1:0 pulse 4 .1 now
sudo wr-dio-cmd /dev/fmc-dio-1:0 pulse 4 .1 now
# Pulse for 10 microseconds in the middle of the next second
wr-dio-cmd /dev/fmc-dio-1:0 pulse 4 .00001 +1.5
sudo wr-dio-cmd /dev/fmc-dio-1:0 pulse 4 .00001 +1.5
# Pulse for 1ms at 17:00 today
wr-dio-cmd /dev/fmc-dio-1:0 pulse 4 .001 $(date +%s --date 17:00)
sudo wr-dio-cmd /dev/fmc-dio-1:0 pulse 4 .001 $(date +%s --date 17:00)
# Get timestamps for the output events above
wr-dio-cmd /dev/fmc-dio-1:0 stamp 4
sudo wr-dio-cmd /dev/fmc-dio-1:0 stamp 4
# Make a train of 5 pulses, 0.5ms wide, every ms at next second
wr-dio-cmd /dev/fmc-dio-1:0 pulse 4 0.0005 +1 .001 5
sudo wr-dio-cmd /dev/fmc-dio-1:0 pulse 4 0.0005 +1 .001 5
# Configure channel 0 as input with termination, 1 as input, 4 as low
wr-dio-cmd /dev/fmc-dio-1:0 mode Ii--0
sudo wr-dio-cmd /dev/fmc-dio-1:0 mode Ii--0
# Generate interrupt now
wr-dio-cmd /dev/fmc-dio-1:0 irq now
sudo wr-dio-cmd /dev/fmc-dio-1:0 irq now
# Generate a train of 100 interrupts every 10 ms starting at the next second
wr-dio-cmd /dev/fmc-dio-1:0 irq +1 .01 100
sudo wr-dio-cmd /dev/fmc-dio-1:0 irq +1 .01 100
# Make a train of indefinite pulses, 1ms wide every 5ms
wr-dio-cmd /dev/fmc-dio-1:0 pulse 1 0.001 now 0.005 -1
sudo wr-dio-cmd /dev/fmc-dio-1:0 pulse 1 0.001 now 0.005 -1
# Stop the previous pulse train
wr-dio-cmd /dev/fmc-dio-1:0 pulse 1 0.001 now 0.005 0
sudo wr-dio-cmd /dev/fmc-dio-1:0 pulse 1 0.001 now 0.005 0
# Update pulse width in channel 1 to 10ms
wr-dio-cmd /dev/fmc-dio-1:0 update_width 1 0.01
sudo wr-dio-cmd /dev/fmc-dio-1:0 update_width 1 0.01
# Disable interrupts in channel 0
wr-dio-cmd /dev/fmc-dio-1:0 mask_irq 0 y
sudo wr-dio-cmd /dev/fmc-dio-1:0 mask_irq 0 y
# Enable interrupts in channel 2
wr-dio-cmd /dev/fmc-dio-1:0 mask_irq 2 Y
sudo wr-dio-cmd /dev/fmc-dio-1:0 mask_irq 2 Y
@end example
......@@ -797,24 +797,24 @@ with a delay of 1ms. The input events in this case are from a @i{pulse-per-secon
@smallexample
tornado.root# /tmp/wr-dio-agent wr0 /dev/fmc-dio-1:0 &
spusa.root# wr-dio-ruler wr1 /dev/fmc-dio-1:0 IN4 L3+.001 R4+.001 R2+.001
spusa.root# sudo wr-dio-ruler wr1 /dev/fmc-dio-1:0 IN4 L3+.001 R4+.001 R2+.001
wr-dio-ruler: configured for local channel 3, delay 0.001000000
wr-dio-ruler: configured for remote channel 4, delay 0.001000000
wr-dio-ruler: configured for remote channel 2, delay 0.001000000
[... wait a few seconds ...]
spusa.root# wr-dio-cmd /dev/fmc-dio-1:0 stamp 3
spusa.root# sudo wr-dio-cmd /dev/fmc-dio-1:0 stamp 3
ch 3, 385.001000000
ch 3, 386.001000000
ch 3, 387.001000000
ch 3, 388.001000000
tornado.root# wr-dio-cmd /dev/fmc-dio-1:0 stamp 2
tornado.root# sudo wr-dio-cmd /dev/fmc-dio-1:0 stamp 2
ch 2, 385.001000000
ch 2, 386.001000000
ch 2, 387.001000000
ch 2, 388.001000000
tornado.root# wr-dio-cmd /dev/fmc-dio-1:0 stamp 4
tornado.root# sudo wr-dio-cmd /dev/fmc-dio-1:0 stamp 4
ch 4, 385.001000000
ch 4, 386.001000000
ch 4, 387.001000000
......@@ -825,8 +825,7 @@ with a delay of 1ms. The input events in this case are from a @i{pulse-per-secon
@node Interrupt Demo
@chapter Interrupt Demo
The interrupt demo software can be found in the root directoy of the wr-starting-kit
repository.
The interrupt demo software can be found in the @code{sw/irq-demo} directoy.
This demo sofware disables the interrupts of all channel except the new one, only
dedicated to interrupts.
By default, it setups the interrupt with 100 milliseconds between them.
......@@ -839,7 +838,7 @@ This is the general syntax of the command:
@table @code
@item demo-irq <dio-device> [<period in ns>]
@item irq-demo <dio-device> [<period in ns>]
@end table
......@@ -847,10 +846,10 @@ Example uses of the tool follow:
@example
# Generate one interrupt each 100 ms
demo-irq /dev/fmc-dio-1:0
sudo irq-demo /dev/fmc-dio-1:0
# Generate one interrupt each 10 ms
demo-irq /dev/fmc-dio-1:0 10000000
sudo irq-demo /dev/fmc-dio-1:0 10000000
@end example
@c ##########################################################################
......
......@@ -35,6 +35,7 @@ static void destroy_user_arguments(user_args args);
static void show_help(void);
static unsigned int check_user_stop(void);
static void set_stdin_as_nonblocking(void);
static void exit_abruptly(int sig);
#endif
......@@ -17,6 +17,7 @@
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>
......@@ -26,6 +27,24 @@
#include "file-log.h"
#include "irq-demo-private.h"
/* Static data for signal handlers */
static fmc_dio_device global_fmc_dev = NULL;
/*
* irq-demo /dev/<fmc-device-file> [<irq period>]
* To exit: Please press 'q' in the keyboard or send a stop signal (CNTR+C)
*
* This DEMO shows the behavior of the interrupts for the FMC DIO device. The basic operation
* is to get all the timestamps generated by the FMC DIO channel and compute a basic statistics
* taking into consideration the system time such as time difference, mean and standard deviation.
*
* In order to work properly, it uses several resources that can be found in under dep folder:
* - loggers: General implementation for logs generation. Two kind of loggers are supported now:
* - printf-log: It uses the stdout for messages.
* - file-log: It uses a specific file for messages.
* - fmc-dio-device: Implementation of FMC DIO device functionalities.
* - stats-engine: Statistics engine code. It contains all the logic to compute the different metrics
*/
int main(int argc, char *argv[])
{
fmc_dio_device dev;
......@@ -38,52 +57,96 @@ int main(int argc, char *argv[])
stats_engine sengine;
int ret = 0;
/* Initialize signal handler for force exit */
signal(SIGINT, exit_abruptly);
signal(SIGQUIT, exit_abruptly);
/* Create the loggers: One for stdout and the other for a specific file */
gen_log = create_printf_log_device();
stats_log = create_file_log_device(STATS_LOG_PATH);
/* Loggers are stored in array:
* -[0]: General logger for stdout
* -[1]: File logger for stats
*/
logs[0] = gen_log;
logs[1] = stats_log;
/* Parse user arguments (FMC DIO dev entry path and optionally irq period) */
user_arguments = create_user_arguments();
if(parse_user_arguments(argc, argv, user_arguments)) {
/* In case of failure, show the help message and exit */
show_help();
ret = 1;
goto out_log;
}
/* Create stats engine to compute timestamps metrics (difference, mean, stdev) */
sengine = create_stats_engine();
if(check_stats_engine(sengine)) {
/* In case of failure, exit */
ret = 1;
goto out_user_args;
}
/* Attach loggers to stats engine
* This allows the engine to generate output messages for the stdout and log file
*/
attach_log_devices_to_stats_engine(sengine, logs, n_logs);
/* Enable log for stats engine (by default is disabled) */
enable_log_for_stats_engine(sengine);
/* Create FMC DIO device using user arguments */
dev = create_fmc_dio_device(user_arguments->fmc_dev_path);
if(open_fmc_dio_device(dev)) {
/* In case of failure, exit */
ret = 1;
goto out_stats_engine;
}
/*
* Attach loggers to FMC DIO device
* This allows the FMC DIO to generate output messages for the stdout and log file
*/
attach_log_devices_to_fmc_dio_device(dev, logs, n_logs);
enable_log_for_fmc_dio_device(dev);
/* Before starting IRQ demo, Interrupts should be properly configured:
* 1) Disable all interrupts
* 2) Enable the TEST_FMC_DIO_CH interrupt line
* 3) Setup specific information for interrupt line (period from user arguments or default one)
*/
disable_fmc_dio_device_all_irq(dev);
enable_fmc_dio_device_irq(dev, TEST_FMC_DIO_CH);
setup_fmc_dio_device_irq(dev, user_arguments->irq_period, TEST_FMC_DIO_COUNT);
/* Configure stdin as non-blocking. It is required for the user check exit function */
set_stdin_as_nonblocking();
/* Save FMC DIO dev in globals for the signal handlers */
global_fmc_dev = dev;
/* Main loop of IRQ demo (until user requests to exit) */
while(!user_stop) {
/* Main logic funtion (get timestamps and process them in the stats engine) */
demo_irq_process_loop(dev, sengine);
/* Check if user has requested to exit */
user_stop = check_user_stop();
}
/* Exit sequence */
/* Disable all interrupts */
disable_fmc_dio_device_all_irq(dev);
out_fmc_dio_device:
/* Close FMC DIO device */
close_fmc_dio_device(dev);
out_stats_engine:
/* Close stats engine */
destroy_stats_engine(sengine);
out_user_args:
/* Free resources for user arguments */
destroy_user_arguments(user_arguments);
out_log:
/* Close loggers */
destroy_log_device(stats_log);
destroy_log_device(gen_log);
......@@ -94,6 +157,12 @@ static void demo_irq_process_loop(fmc_dio_device fmc_dev, stats_engine engine)
{
struct timespec *ts;
unsigned int nts;
/* Process loop:
* - Get timestamps from FMC DIO device (specific channel under testing)
* - Pass them to the stats engine and generate the statistics
* - Sleep for a while to avoid excesive CPU consumption
*/
while(!get_utc_ts_from_fmc_dio_device(fmc_dev, TEST_FMC_DIO_CH, &ts, &nts)) {
process_timestamps_to_engine(engine, ts, nts);
usleep(PROCESS_SLEEP_US);
......@@ -104,9 +173,13 @@ static void process_timestamps_to_engine(stats_engine engine, struct timespec *t
unsigned int nts)
{
for(int i = 0 ; i < nts ; i++) {
/* Pass a timestamp to stats engine */
add_usr_timestamp_to_stats_engine(engine, &ts[i]);
/* Compute stats taking into consideration all the timestamps inside the engine */
run_stats_engine(engine);
}
/* Finally, free memory for timestamps (reserved by FMC DIO device) */
free(ts);
}
......@@ -148,22 +221,20 @@ static void show_help(void)
static unsigned int check_user_stop(void)
{
int ret = 0;
char c;
fd_set fds;
struct timeval tv;
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
c = getchar();
tv.tv_sec = 0;
tv.tv_usec = 1;
return (c == 'q');
}
if(select(STDIN_FILENO+1, &fds, NULL, NULL, &tv) == 1) {
c = getchar();
if(c == 'q')
ret = 1;
}
static void set_stdin_as_nonblocking(void)
{
fcntl (STDIN_FILENO, F_SETFL, O_NONBLOCK);
}
return ret;
static void exit_abruptly(int sig)
{
disable_fmc_dio_device_all_irq(global_fmc_dev);
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