#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/mman.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#include <rtdm/serial.h>
#define MAIN_PREFIX "main : "
#define WTASK_PREFIX "write_task: "
#define RTASK_PREFIX "read_task: "
#define WRITE_FILE "/dev/rtdm/rtser0"
#define READ_FILE "/dev/rtdm/rtser1"
int read_fd = -1;
int write_fd = -1;
#define STATE_FILE_OPENED 1
#define STATE_TASK_CREATED 2
unsigned int read_state = 0;
unsigned int write_state = 0;
RTIME write_task_period_ns = 100000000llu;
RT_TASK write_task;
RT_TASK read_task;
.baud_rate = 115200,
.parity = RTSER_DEF_PARITY,
.data_bits = RTSER_DEF_BITS,
.handshake = RTSER_DEF_HAND,
.fifo_depth = RTSER_DEF_FIFO_DEPTH,
.rx_timeout = RTSER_DEF_TIMEOUT,
.tx_timeout = RTSER_DEF_TIMEOUT,
.event_timeout = 1000000000,
.timestamp_history = RTSER_RX_TIMESTAMP_HISTORY,
.event_mask = RTSER_EVENT_RXPEND,
};
.
config_mask = RTSER_SET_BAUD | RTSER_SET_TIMESTAMP_HISTORY,
.baud_rate = 115200,
.timestamp_history = RTSER_DEF_TIMESTAMP_HISTORY,
};
static int close_file( int fd, char *name)
{
int err, i=0;
do {
i++;
err = close(fd);
switch (err) {
case -EAGAIN:
printf(MAIN_PREFIX "%s -> EAGAIN (%d times)\n",
name, i);
break;
case 0:
printf(MAIN_PREFIX "%s -> closed\n", name);
break;
default:
printf(MAIN_PREFIX "%s -> %s\n", name,
strerror(errno));
break;
}
} while (err == -EAGAIN && i < 10);
return err;
}
static void cleanup_all(void)
{
if (read_state & STATE_FILE_OPENED) {
close_file(read_fd, READ_FILE" (read)");
read_state &= ~STATE_FILE_OPENED;
}
if (write_state & STATE_FILE_OPENED) {
close_file(write_fd, WRITE_FILE " (write)");
write_state &= ~STATE_FILE_OPENED;
}
if (write_state & STATE_TASK_CREATED) {
printf(MAIN_PREFIX "delete write_task\n");
write_state &= ~STATE_TASK_CREATED;
}
if (read_state & STATE_TASK_CREATED) {
printf(MAIN_PREFIX "delete read_task\n");
read_state &= ~STATE_TASK_CREATED;
}
}
static void catch_signal(int sig)
{
cleanup_all();
printf(MAIN_PREFIX "exit\n");
return;
}
static void write_task_proc(void *arg)
{
int err;
RTIME write_time;
ssize_t sz = sizeof(RTIME);
int written = 0;
if (err) {
printf(WTASK_PREFIX "error on set periodic, %s\n",
strerror(-err));
goto exit_write_task;
}
while (1) {
if (err) {
printf(WTASK_PREFIX
"error on rt_task_wait_period, %s\n",
strerror(-err));
break;
}
written = write(write_fd, &write_time, sz);
if (written < 0 ) {
printf(WTASK_PREFIX "error on write, %s\n",
strerror(errno));
break;
} else if (written != sz) {
printf(WTASK_PREFIX "only %d / %zd byte transmitted\n",
written, sz);
break;
}
}
exit_write_task:
if ((write_state & STATE_FILE_OPENED) &&
close_file(write_fd, WRITE_FILE " (write)") == 0)
write_state &= ~STATE_FILE_OPENED;
printf(WTASK_PREFIX "exit\n");
}
static void read_task_proc(void *arg)
{
int err;
int nr = 0;
RTIME read_time = 0;
RTIME write_time = 0;
RTIME irq_time = 0;
ssize_t sz = sizeof(RTIME);
int rd = 0;
printf(" Nr | write->irq | irq->read | write->read |\n");
printf("-----------------------------------------------------------\n");
while (1) {
if (err) {
printf(RTASK_PREFIX
"error on RTSER_RTIOC_WAIT_EVENT, %s\n",
strerror(errno));
if (err == -ETIMEDOUT)
continue;
break;
}
rd = read(read_fd, &write_time, sz);
if (rd == sz) {
printf("%3d |%16llu |%16llu |%16llu\n", nr,
irq_time - write_time,
read_time - irq_time,
read_time - write_time);
nr++;
} else if (rd < 0 ) {
printf(RTASK_PREFIX "error on read, code %s\n",
strerror(errno));
break;
} else {
printf(RTASK_PREFIX "only %d / %zd byte received \n",
rd, sz);
break;
}
}
if ((read_state & STATE_FILE_OPENED) &&
close_file(read_fd, READ_FILE " (read)") == 0)
read_state &= ~STATE_FILE_OPENED;
printf(RTASK_PREFIX "exit\n");
}
int main(int argc, char* argv[])
{
int err = 0;
signal(SIGTERM, catch_signal);
signal(SIGINT, catch_signal);
write_fd = open( WRITE_FILE, 0);
if (write_fd < 0) {
printf(MAIN_PREFIX "can't open %s (write), %s\n", WRITE_FILE,
strerror(errno));
goto error;
}
write_state |= STATE_FILE_OPENED;
printf(MAIN_PREFIX "write-file opened\n");
if (err) {
printf(MAIN_PREFIX "error while RTSER_RTIOC_SET_CONFIG, %s\n",
strerror(errno));
goto error;
}
printf(MAIN_PREFIX "write-config written\n");
read_fd = open( READ_FILE, 0 );
if (read_fd < 0) {
printf(MAIN_PREFIX "can't open %s (read), %s\n", READ_FILE,
strerror(errno));
goto error;
}
read_state |= STATE_FILE_OPENED;
printf(MAIN_PREFIX "read-file opened\n");
if (err) {
printf(MAIN_PREFIX "error while ioctl, %s\n",
strerror(errno));
goto error;
}
printf(MAIN_PREFIX "read-config written\n");
if (err) {
printf(MAIN_PREFIX "failed to create write_task, %s\n",
strerror(-err));
goto error;
}
write_state |= STATE_TASK_CREATED;
printf(MAIN_PREFIX "write-task created\n");
if (err) {
printf(MAIN_PREFIX "failed to create read_task, %s\n",
strerror(-err));
goto error;
}
read_state |= STATE_TASK_CREATED;
printf(MAIN_PREFIX "read-task created\n");
printf(MAIN_PREFIX "starting write-task\n");
if (err) {
printf(MAIN_PREFIX "failed to start write_task, %s\n",
strerror(-err));
goto error;
}
printf(MAIN_PREFIX "starting read-task\n");
if (err) {
printf(MAIN_PREFIX "failed to start read_task, %s\n",
strerror(-err));
goto error;
}
for (;;)
pause();
return 0;
error:
cleanup_all();
return err;
}