Why doesn't rx receive data from loopback tx on UART? - c

I have a system running Linux, connected the rx to the tx (loopback) from UART1 and executed this code:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
int main(void) {
int iFd = open("/dev/ttyTHS0", O_RDWR);
if (iFd < 0) {
fprintf(stdout, "Error when opening file.\n");
return -1;
}
while (1) {
if (write(iFd, "A", strlen("A")) == -1) {
fprintf(stdout, "Failed to write\n");
return -1;
}
char buff[10] = {
0
};
if (read(iFd, buff, sizeof(buff)) < 0) {
fprintf(stdout, "Failed to read.\n");
return -1;
}
fprintf(stdout, "read: %s\n", buff);
}
close(iFd);
return 0;
}
The thing is it doesn't seem to receive any data. The code simply blocks at read. I can see the data being transmitted on the tx line when looking at it with an oscilloscope, but the rx doesn't receive anything. I have also tried splitting this code in 2 processes, one process for the transmission and another one for the reception, but that doesn't work either.

It is logical. You probably do not send anything as it is sits in the send buffer. Other problem is that you try to receive 10 bytes, but send only one. On many systems serial timeouts are set to infinitive time and you will wait forever for the next 9 bytes.
what to do (point 2 has some variants):
flush the UART file
2a. read only as many bytes as you sent
ioctl(ifd, FIONREAD, &bytes_ready_to_read); and then read only the number available.
2c. change the timeout.

Related

Bytes are not sent to the serial driver buffer

I have this program:
// C headers
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdint.h>
// POSIX headers
#include <unistd.h>
#include <sys/ioctl.h>
// Other headers
#include "ZL_sleep.h"
#include "ZL_utf8.h"
#include "ZL_serial.h"
#define BS 4 // Buffer size
int main(int argc, char * argv[]){
int32_t p; // Port
int32_t r; // Read finished
uint8_t b[BS]; // Buffer
uint32_t n; // Number of bytes to be read from driver buffer
if(argc != 2){
printf("ERROR: Supply a \"serial port\" device file.");
exit(EXIT_FAILURE);
}
p = ZL_open_tty(argv[1]);
if(p < 0){
perror("ERROR: open()");
exit(EXIT_FAILURE);
}
while(1){
memset(b, '\0', BS);
r = read(p, b, BS);
if(r < 0){
if(errno == EAGAIN){
}
else{
perror("ERROR: read()");
close(p);
exit(EXIT_FAILURE);
}
}
ZL_utf8_print_bytes(b, BS);
putchar('\n');
}
close(p);
return EXIT_SUCCESS;
}
that uses function ZL_utf8_print_bytes() that prints the buffer bytes (one by one in a for loop). It also calls function ZL_open_tty() and passes the argv[1] (/dev/pts/1) to it as an argument.
Function ZL_open_tty() function sets O_NONBLOCK flag with open() in order for open() to return immediately i.e. "nonblocking" with whatever status. Then before any other I/O function is used, function clears O_NONBLOCK flag and switches back to "blocking". It then sets VMIN and VTIME so that read():
blocks until VMIN or more bytes is received/exists in driver
buffer. (It may block indefinitely)
uint32_t ZL_open_tty(const char * terminal){
uint32_t fd; // File's descriptor
uint32_t fl; // File's flags
struct termios fo; // File's options
fd = open(terminal, O_RDWR | O_NOCTTY | O_NONBLOCK);
if(fd < 0){
return -1;
}
fl = fcntl(fd, F_GETFL, 0);
if(fl < 0){
perror("ERROR: fcntl():");
return -1;
}
fcntl(fd, F_SETFL, fl & ~(O_NONBLOCK | O_APPEND | O_DSYNC | O_RSYNC | O_SYNC));
tcgetattr(fd, &fo);
fo.c_cc[VMIN] = 1;
fo.c_cc[VTIME] = 0;
tcsetattr(fd, TCSANOW, &fo);
fputs("─────────────────────────────────────────────────── terminal settings\n", stdout);
printf("VMIN = %d\n", fo.c_cc[VMIN]);
printf("VTIME = %d\n", fo.c_cc[VTIME]);
putchar('\n');
return(fd);
Afterwards my program enters an endless while loop where read() blocks until I enter any key when keyboard focus is in /dev/pts/1.
The problem that I am facing is that sometimes I press a key in /dev/pts/1 and bytes registered with this key aren't transmitted to the driver buffer?! Bytes just stays in the /dev/pts/1. This happens with ASCII (1-byte) characters and UTF8 (multi-byte) bytes...
I know that read() tries to read requested amount of bytes (BS) from the driver buffer. But it reads less bytes if there aren't BS bytes available in the driver buffer. So... if some bytes would arrive later it could read them later. But these bytes never arrive to the driver buffer for some reason...
What could be causing bytes not to arrive in the driver buffer and remain forever in the /dev/pts/1?
The pts was created when a virtual terminal was attached to the system (usually ssh). The pts was connected as stdin/stdout for a shell which was started for the connection, therefore you already have a process attached to the pts and reading from it.
Once you attach your application, you effectively start a race between both processes (your application and the shell), so whoever is faster will receive the content of the buffer. The character had not remained in the buffer of the pts, rather it was read by the shell attached to the pts.
To be able to read without interruption from the attached process, you need to intercept the buffer of the pts by informing the master multiplexer ptmx, see more in ptmx(4). You can study how it's done in the interceptty

SIGXFSZ is sent by kernel unless something is printed to stdout?

I am learning "Advanced Programming in Unix Environment", and have a problem with exercise no.11 in chapter 10.
In my program, I set RLIMIT_FSIZE to 1024.
So the kernel should send SIGXFSZ to my program when write trying to exceed that limit.
But I found that SIGXFSZ is not send unless something is printed to stdout.
Here is my code:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <signal.h>
#define BUFFSIZE 100
void xfsz_handler(int signo)
{
fprintf(stderr, "%d, %s\n", signo, strsignal(signo));
}
int main(int argc, char* argv[])
{
int n;
char buf[BUFFSIZE];
struct rlimit fsizeLimit;
fsizeLimit.rlim_cur=1024;
fsizeLimit.rlim_max=1024;
if(setrlimit(RLIMIT_FSIZE, &fsizeLimit) < 0)
{
perror("setrlimit error");
exit(-1);
}
if(signal(SIGXFSZ, xfsz_handler)==SIG_ERR)
{
fprintf(stderr, "set signal handler error for %d\n", SIGXFSZ);
exit(-1);
}
printf("what ever\n"); /* we need this to get SIGXFSZ sent */
while ( (n=read(STDIN_FILENO, buf, BUFFSIZE)) > 0)
{
int byteWrite = 0;
if ( (byteWrite = write(STDOUT_FILENO, buf, n)) < 0)
{
perror("write error");
exit(-1);
}
if(byteWrite!=n)
{
fprintf(stderr, "byteWrite=%d, n=%d\n", byteWrite, n);
exit(-1);
}
}
if (n<0)
{
perror("read error");
exit(-1);
}
return 0;
}
if I comment out the following line in the code, kernel will not transmit SIGXFSZ.
printf("What ever . . . \n");
Why this happens? Thanks in advance.
[root#luaDevelopment ex11]# ./myCopy < /root/workspace/AdvanceProgrammingInTheUnixEnvironment.20140627.tar.bz2 >aa.tar.bz2
byteWrite=24, n=100
[root#luaDevelopment ex11]# make
gcc -o myCopy myCopy.c -std=gnu99 -I../../lib/ -L../../lib/ -lch10
[root#luaDevelopment ex11]# ./myCopy < /root/workspace/AdvanceProgrammingInTheUnixEnvironment.20140627.tar.bz2 >aa.tar.bz2
byteWrite=24, n=100
25, File size limit exceeded
[root#luaDevelopment ex11]#
user3693690 found the answer in Appendix C of the book:
10.11 Under Linux 3.2.0, Mac OS X 10.6.8, and Solaris 10, the signal handler for SIGXFSZ is never called because the loop exits the program on a short write, but write returns a count of 24 as soon as the file’s size reaches 1,024 bytes. When the file’s size has reached 1,000 bytes under FreeBSD 8.0, the signal handler is called on the next attempt to write 100 bytes, and the write call returns −1 with errno set to EFBIG("File too big"). On all four platforms, if we attempt an additional write at the current file offset (the end of the file), we will receive SIGXFSZ and write will fail, returning −1 with errno set to EFBIG.

Redundancy when reading USB serial port (C;Mac OSX;Arduino)

I'm writing a simple C program that can read data from a USB port that is connected to my Arduino device. The Arduino outputs data at a baud rate of 9600 in chunks of 4 bytes.
I want the input from the Arduino to my computer to look something like this:
136.134.132.130.129.127.126.124.121.119.117.115.113.111.
However, I'm getting something like this:
271.274.281..2.4062.4022.40225.4021
Question: How do I get the input in my C program to neatly synchronize with out loosing data/ rereading data? Are there some kind of flags that could tell my program when the port has new data?
Code:
#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <sys/types.h>
int open_port(void)
{
int fd; /* File descriptor for the port */
fd = open("/dev/tty.usbmodemfd121", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
perror("open_port: Unable to open /dev/tty");
}
else
fcntl(fd, F_SETFL, 0);
struct termios options;
tcgetattr(fd,&options);
cfsetospeed(&options,B9600);
options.c_cflag |=(CLOCAL | CREAD);
tcsetattr(fd, TCSANOW, &options);
return (fd);
}
int main (){
int i;
for(i=0; i<50; i++){
fcntl(open_port(), F_SETFL, FNDELAY);
char buf[5];
size_t nbytes;
ssize_t bytes_read;
nbytes = sizeof(buf);
bytes_read = read(open_port(), buf, nbytes);
printf("%s ", buf);
buf[0]=0;
}
return 0;
}
Your program does not properly open() the serial port for reading it.
In fact it repeatedly opens it two times every iteration of the for loop.
The device should be opened only once by your program.
Instead of
for (i=0; i<50; i++) {
fcntl(open_port(), F_SETFL, FNDELAY);
bytes_read = read(open_port(), buf, nbytes);
}
the main program should be structured like
fd = open_port();
if (fd < 0) {
/* handle error condition */
}
rc = fcntl(fd, F_SETFL, FNDELAY);
if (rc < 0) {
/* handle error condition */
}
for (i=0; i<50; i++) {
bytes_read = read(fd, buf, nbytes);
if (bytes_read < 0) {
/* handle error condition */
}
}
close(fd);
Your program is too "simple". It sets only a few attributes, and doesn't bother to check the return codes of system calls.
Is this supposed to be canonical or non-canonical (aka raw) mode (i.e. is the data ASCII text or binary)?
Refer to this Serial Programming Guide for proper setup of the serial port.
read data from a USB port
USB is a bus.
The device your program reads from is a serial port attached to that USBus.
Second coding issue
Your original code may print garbage data.
nbytes = sizeof(buf);
bytes_read = read(open_port(), buf, nbytes);
printf("%s ", buf);
buf[0]=0;
The bytes returned by the read() operation are not likely to be terminated by a NULL byte, so a string operation on that read buffer could exceed the bounds of the allocated array.
Code that would not misbehave would be something like:
nbytes = sizeof(buf) - 1;
bytes_read = read(fd, buf, nbytes);
if (bytes_read < 0) {
/* handle error condition */
} else {
buf[bytes_read] = 0; /* append terminator */
printf("%s ", buf);
}
Note that nbytes is one less than the allocated size of the buffer.
This is to ensure that there is an available byte to store the string terminator byte when the read() operation returns a "full" buffer of nbytes.
For efficiency the assignment of nbytes should be performed before entering the for loop, rather than within the loop.

Linux Serial Port in C [duplicate]

This question already has answers here:
Reading from a serial port after writing on it
(5 answers)
Closed 8 years ago.
I have written a program in c for reading and writing serial port.But the problem is I am using while loop and it is continuously sending the command over the serial port.
I want to write some command on serial port
wait for answer
write another command
wait for some answer and so on
My code goes like this:-
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h>
#include <errno.h>
#include <time.h>
int main()
{
printf("\n");
printf("Please wait till serial Port is being Initialized .... \n");
sleep(2);
printf("\n................. Initializing ................\n");
sleep(2);
printf("\n");
printf("\n\n");
static int fd = 0;
int len;
char res[100];
char s[100] = " Hellow World";
struct termios options;
//==================================================================
// hard coaded port ttyO3
//==================================================================
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
fcntl(fd, F_SETFL, O_NONBLOCK);
//==================================================================
// Error Handling
//==================================================================
if (fd < 0)
{
printf("Serial open error %d %s\n", errno, strerror(errno));
}
printf("\n");
printf("\n==================================================\n");
//==================================================================
// Get the current options for the port...
//==================================================================
tcgetattr(fd, &options);
//==================================================================
// Set the baud rates to 115200...
//==================================================================
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
//=================================================================
// Enable the receiver and set local mode..
//==================================================================
options.c_cflag |= (CLOCAL | CREAD);
//==================================================================
// Set the new options for the port...
//==================================================================
tcsetattr(fd, TCSANOW,&options);
while(1)
{
write(fd,s,strlen((char*)s));
sleep(1);
len = read(fd,res,100);
if (len < 0)
{
if (errno == EAGAIN)
{
continue;
}
else
{
printf("read error %d %s\n", errno, strerror(errno));
}
}
else
{
res[len < 100 ? len:100] ='\0';
printf("read %d chars: %s\n",len, res);
}
}
close(fd);
}
where am I getting wrong.
Thanks and Regards
It looks like the file descriptor is opened as non-blocking (fcntl(fd, F_SETFL, O_NONBLOCK);). You must have some blocking operation if you want to wait for data to be read.
You can make the file descriptor blocking, or use some asynchronous manager like select.
Since you make your file descriptor non-blocking (twice), you have to as the system to wait between the steps. A common way to do this is the select system call, which you can use to wait until there is something to read from the file descriptor.
Can be done something like this:
write(...);
fd_set poll_set;
FD_ZERO(&poll_set);
FD_SET(fd, &poll_set);
/* Wait, with no timeout, for something to be readable */
int rc = select(fd + 1, &poll_set, NULL, NULL, NULL);
if (rc == -1)
{
perror("select");
}
else
{
/* Continue to next step, where you read */
}
Also note that the read-calls may actually not receive the complete messages in the first attempt. You may have to read multiple times to get the complete message. If your messages are of a fixed size, then read in a loop while decreasing the amount of bytes to read until you have received the complete message. If your message have a end-of-message marker, then read byte by byte until you receive it. If your messages contain a header with the message size, then use the first fixed-size read method twice, once to get the header and once to get the data.

Why is this message not only displayed when a file is written to (using the poll C Linux function)?

I was reading about poll in C programming and built an application given on the poll(2) man page.
Here is the example:
#include<stdio.h>
#include <stropts.h>
#include <poll.h>
#include <fcntl.h>
int main() {
struct pollfd fds[2];
int timeout_msecs = -1;
int ret;
int i;
/* Open STREAMS device. */
fds[0].fd = open("/home/jeshwanth/mywork/poll/dev0", O_RDONLY);
fds[1].fd = open("/home/jeshwanth/mywork/poll/dev1", O_RDONLY);
fds[0].events = POLLOUT | POLLWRBAND;
fds[1].events = POLLOUT | POLLWRBAND;
while (1) {
ret = poll(fds, 2, timeout_msecs);
if (ret > 0) {
/* An event on one of the fds has occurred. */
for (i = 0; i < 2; i++) {
if (fds[i].revents != 0) {
/* Priority data may be written on device number i. */
printf(
"Priority Data may be written on device number %d POLLWRBAND\n",
i);
}
if (fds[i].revents = !0) {
/* Data may be written on device number i. */
printf("Data may be written on device number %d POLLOUT\n",
i);
}
if (fds[i].revents = !0) {
/* A hangup has occurred on device number i. */
printf("A hangup has occurred on device number %d\n", i);
}
}
}
}
return 0;
}
Note: dev0 and dev1 are normal files. When I run the program, if no event occurred in dev0 and dev1, the message is displayed. But I was expecting when some write into the file happens, only then should it display the message. Am I wrong?
Polling it for output readiness doesn't mean you will get notified when some output occurs: it means that you'll get notified when there is output buffer space available so you can output (but you should still check the return value of your output function. The buffer state may have changed between polling and outputting; always check return values).
Minimal FIFO named pipe example
You won't be able to see anything interesting with regular files, since those always give POLLIN immediately: How can select() wait on regular file descriptors (non-sockets)?
The simplest way to play around with poll is to use named pipes as shown below. This should prepare you for their major application: sockets and device files.
Source below. Usage:
sudo mknod poll0.tmp p
sudo mknod poll1.tmp p
sudo chmod 666 poll*.tmp
./poll.out
On another shell:
printf a > poll0.tmp
printf b > poll1.tmp
Output:
loop
POLLIN i=0 n=1 buf=a
loop
POLLHUP i=0
loop
POLLIN i=1 n=1 buf=b
POLLHUP i=1
loop
So notice how poll waits for the reads without looping.
Cooler example:
(while true; do date; sleep 1; done) > poll0.tmp &
(while true; do date; sleep 2; done) > poll1.tmp &
0 gets written every one second, and 1 every two seconds, which shows how poll() is dealing with both inputs concurrently, without stalling each other.
Source:
#define _XOPEN_SOURCE 700
#include <fcntl.h> /* creat, O_CREAT */
#include <poll.h> /* poll */
#include <stdio.h> /* printf, puts, snprintf */
#include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS */
#include <unistd.h> /* read */
int main(void) {
enum { N = 2 };
char buf[1024], path[1024];
int fd, i, n;
short revents;
struct pollfd pfds[N];
for (i = 0; i < N; ++i) {
snprintf(path, sizeof(path), "poll%d.tmp", i);
/* O_NONBLOCK is required or else the open blocks
* until the other side of the pipe opens. */
fd = open(path, O_RDONLY | O_NONBLOCK);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
pfds[i].fd = fd;
/* Only events in this mask will be listened to.
* However, there are also some events that are unmaskable,
* notably POLLHUP when pipe closes! */
pfds[i].events = POLLIN;
}
while (1) {
puts("loop");
i = poll(pfds, N, -1);
if (i == -1) {
perror("poll");
exit(EXIT_FAILURE);
}
for (i = 0; i < N; ++i) {
revents = pfds[i].revents;
if (revents & POLLIN) {
n = read(pfds[i].fd, buf, sizeof(buf));
printf("POLLIN i=%d n=%d buf=%.*s\n", i, n, n, buf);
}
if (revents & POLLHUP) {
printf("POLLHUP i=%d\n", i);
/* This happens when the other side closed.
* This event is only cleared when we close the reader. */
/* poll won't set POLLHUP anymore once all fds are closed.
* Any futher polls on this will give the POLLNVAL event instead. */
close(pfds[i].fd);
/* negative fds are ignored. So if we negate an FD,
* we can both turn if off for a while, and turn it on
* later on by re-nagating it. */
pfds[i].fd *= -1;
}
}
}
}
Compile with:
gcc -o poll.out -std=c99 poll.c
Tested in Ubuntu 14.04.
GitHub upstream.
The lines:
close(pfds[i].fd);
pfds[i].fd *= -1;
are required or else you get POLLHUP forever, see also: How to use the poll C function to watch named pipes in Linux?
For even more fun, create a Linux kernel module what implements the poll fops: How to add poll function to the kernel module code?
I'll give you a hint on how to correct it. revents is interpreted as several bit flags.
/* check for priority write readiness */
if (fds[i].revents & POLLWRBAND) {
printf("Priority Data may be written on device number %d POLLWRBAND\n", i);
}
/* check for write readiness */
if (fds[i].revents & POLLOUT) {
printf("Data may be written on device number %d POLLOUT\n", i);
}
/* check for hang-up */
if (fds[i].revents & POLLHUP) {
printf("A hangup has occurred on device number %d\n", i);
}

Resources