poll() returns both, POLLPRI & POLLERR - c

I started to get in C programming with Linux and embedded systems (router hardware and openwrt). I have got interupts on GPIOs enabled, using poll works ... nearly.
I can use poll() and if i press the button to trigger the interrupt, poll() returns with a value > 0. So far so good. Now i try to use poll() on several GPIOs simultaniosly and therefor want to analyze the revents of every potential interrupt source. Allthough the interrupt seems to work, i get POLLPRI & POLLERR back and i do not understand why. Reducing the pollfd structure to 1 entry does not change anything.
char value;
int fd_btn1 = open("/sys/class/gpio/gpio14/value", O_RDONLY);
int fd_left = open("/sys/class/gpio/gpio12/value", O_RDONLY);
int fd_right = open("/sys/class/gpio/gpio13/value", O_RDONLY);
struct pollfd fds[3];
fds[0].fd = fd_btn1;
fds[1].fd = fd_left;
fds[2].fd = fd_right;
fds[0].events = POLLPRI;
fds[1].events = POLLPRI;
fds[2].events = POLLPRI;
read(fd_btn1, &value, 1);
read(fd_left, &value, 1);
read(fd_right, &value, 1);
ret = poll(fds, 1, 10000);
//debugging purpose
printf("ret: %i - revents[0]: %i", ret, fds[0].revents);
In case button was pressed (interrupt triggered):
ret=1d, revents=10d
In case nothing was pressed, both is 0d

I've found some answer alluding to your question at: http://e2e.ti.com/support/dsp/davinci_digital_media_processors/f/716/t/182883
I just ran into the POLLERR thing you're seeing too. Turns out this is
how all sysfs files work, and you're using gpio through the sysfs
interface.
From the sysfs GPIO kernel document: If the pin can be configured as
interrupt-generating interrupt and if it has been configured to
generate interrupts (see the description of "edge"), you can poll(2)
on that file and poll(2) will return whenever the interrupt was
triggered. If you use poll(2), set the events POLLPRI and POLLERR.
Also, if you look take a look at the kernel code in fs/sysfs/file.c,
you'll see that sysfs_poll returns DEFAULT_POLLMASK | POLLERR |
POLLPRI.
All that said, it does seem strange that sysfs files return
POLLERR, I'm not sure why they chose to do that.

Related

Waiting for serial transmission to complete in Win32

I seem to be having a bit of trouble in waiting for the completion of serial data transmissions.
My interpretation of the relevant MSDN article is the EV_TXEMPTY event is the correct signal and which indicates that:
EV_TXEMPTY - The last character in the output buffer was sent.
However in my tests the event always fires immediately as soon as the data has been submitted to the buffer and long before the final has actually reached the wire. See the repro code below where the period is always zero.
Have I made an error in the implementation, am I misunderstanding the purpose of the flag, or is this feature simply not supported by modern drivers? In the latter case is there a viable workaround, say some form of synchronous line state request?
For the record the tests were conducted with FTDI USB-RS485 and TTL-232R devices in a Windows 10 system, a USB-SERIAL CH340 interface on a Windows 7 system, as well as the on-board serial interface of a 2005-vintage Windows XP machine. In the FTDI case sniffing the USB bus reveals only bulk out transactions and no obvious interrupt notification of the completion.
#include <stdio.h>
#include <windows.h>
static int fatal(void) {
fprintf(stderr, "Error: I/O error\n");
return 1;
}
int main(int argc, const char *argv[]) {
static const char payload[] = "Hello, World!";
// Use a suitably low bitrate to maximize the delay
enum { BAUDRATE = 300 };
// Ask for the port name on the command line
if(argc != 2) {
fprintf(stderr, "Syntax: %s {COMx}\n", argv[0]);
return 1;
}
char path[MAX_PATH];
snprintf(path, sizeof path, "\\\\.\\%s", argv[1]);
// Open and configure the serial device
HANDLE handle = CreateFileA(path, GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, 0, NULL);
if(handle == INVALID_HANDLE_VALUE)
return fatal();
DCB dcb = {
.DCBlength = sizeof dcb,
.BaudRate = BAUDRATE,
.fBinary = TRUE,
.ByteSize = DATABITS_8,
.Parity = NOPARITY,
.StopBits = ONESTOPBIT
};
if(!SetCommState(handle, &dcb))
return fatal();
if(!SetCommMask(handle, EV_TXEMPTY))
return fatal();
// Fire off a write request
DWORD written;
unsigned int elapsed = GetTickCount();
if(!WriteFile(handle, payload, sizeof payload, &written, NULL) ||
written != sizeof payload)
return fatal();
// Wait for transmit completion and measure time elapsed
DWORD event;
if(!WaitCommEvent(handle, &event, NULL))
return fatal();
if(!(event & EV_TXEMPTY))
return fatal();
elapsed = GetTickCount() - elapsed;
// Display the final result
const unsigned int expected_time =
(sizeof payload * 1000 /* ms */ * 10 /* bits/char */) / BAUDRATE;
printf("Completed in %ums, expected %ums\n", elapsed, expected_time);
return 0;
}
The background is that this is part of a Modbus RTU protocol test suite where I am attempting to inject >3.5 character idle delays between characters on the wire to validate device response.
Admittedly, an embedded realtime system would have been more far suitable for the task but for various reasons I would prefer to stick to a Windows environment while controlling the timing as best as possible.
According to the comments by #Hans Passant and #RbMm the output buffer being referred in the EV_TXEMPTY documentation is an intermediate buffer and the event indicates that data has been forwarded to the driver. No equivalent notification event is defined which encompasses the full chain down to the final device buffers.
No general workaround is presently clear to me short of a manual delay based upon the bitrate and adding a significant worst-case margin for any remaining buffer layers to be traversed, inter-character gaps, clock skew, etc.
I would therefore very much appreciate answers with better alternate solutions.
Nevertheless, for my specific application I have implemented a viable workaround.
The target hardware is a half-duplex bus with a FTDI RS485 interface. This particular device offers an optional local-echo mode in which data actively transmitted onto the bus is not actively filtered from the reception.
After each transmission I am therefore able to wait for the expected echo to appear as a round-trip confirmation. In addition, this serves to detect certain faults such as a short-circuited bus.

GPIO poll exits immediately

I need to free the processor while I wait for a change in the level of a GPIO pin (either rising or falling edge), so I created a simple code to poll a GPIO sysfs value file, but I'm running into some trouble:
In the first poll() call, it exits imediatelly, with both POLLPRI and POLLERR set in revents;
After this, I lseek() and read() the fd, and loop back to poll();
Now poll() hangs.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <poll.h>
#include <sys/fcntl.h>
#define GPIO_DIR "/sys/class/gpio/"
#define GPIO_EXPORT GPIO_DIR "export"
int main(int argc, char **argv)
{
int gpio_fd;
struct pollfd gpio_fdset[1];
char pin_value[] = GPIO_DIR "gpioXYZ/value";
sprintf(pin_value, GPIO_DIR "gpio%s/value", argv[1]);
gpio_fd = open(pin_value, O_RDONLY);
while (1)
{
char buffer[64];
gpio_fdset[0].fd = gpio_fd;
gpio_fdset[0].events = POLLPRI;
gpio_fdset[0].revents = 0;
poll(gpio_fdset, 1, -1);
if (gpio_fdset[0].revents & POLLPRI)
{
printf("revents returned POLLPRI!\n");
lseek(gpio_fdset[0].fd, 0, SEEK_SET);
read(gpio_fdset[0].fd, buffer, 64);
}
}
}
Before calling it, I export the pin I wish to monitor (GPIO1_30 or 62 in the kernel numbering scheme). I've tried setting this pin as input, output, generating interrupts on rising and falling edges, but the behaviour is always the same. What am I missing?
From what I've read, when I use the sysfs, I should not need to use the gpio_request(), gpio_to_irq() and other related functions to be able to poll this pin. Is this right?
Regards,
Guilherme
I've discovered how to overcome this issue. Simply perform a dummy read() after setting opening the file descriptor. Apparently this is due to the fact that a recently opened fd is considered as changed (at least for GPIOs). As for the POLLERR on revents, this is standard sysfs behaviour.
If I understand your requirement right, then you want to take some action when the pin goes high.
you can poll the pin in application layer it self.
Download the "SimpleGPIO.h" and "SimpleGPIO.cpp" from the below URL:
https://github.com/derekmolloy/beaglebone
The SimpleGPIO.h/cpp is self explanatory and you can do all operations with GPIO using the simple function calls.
This one will work fine for any am335x processor. Then to poll you can use in your code some thing like this
int main()
{
//Your code
while(1)
{
if(gpio_get_value())
{
//Do what ever you want to do.
}
}
}
NOTE::
If you want to send any signal to your application process from kernel level using irq then the approach will be little different, But only for polling this code will work fine.
Hope this helps.
Edit:
Please refer below url for more details, it explains your question. You need to use any signal between (Signal number 32 to 64) to detect the change of GPIO status. You need to register your processId with your kernel module.
http://yongbingchen.github.io/blog/2013/03/11/sending-a-signal-from-linux-kernel/
When there is a change in GPIO status, Kernel sends a signal to application layer on which a dedicated function in application layer can execute.

how to detect a pin change of a GPIO on Linux board

I am using 3.12 kernel on an ARM based linux board (imx233 CPU). My purpose is to detect pin change of a GPIO (1 to 0).
I can read the pin value constantly calling the below function (in a while(1) loop)
int GPIO_read_value(int pin){
int gpio_value = 0;
char path[35] = {'\0'};
FILE *fp;
sprintf(path, "/sys/class/gpio/gpio%d/value", pin);
if ((fp = fopen(path,"rb+")) == NULL){ //echo in > direction
//error
}
fscanf(fp, "%d", &gpio_value);
fclose(fp);
return gpio_value;
}
But it causes too much load to the CPU. I don't use usleep or nanosleep, because the pin change happens for a very short of a time that would cause me to miss the event.
As far as I find out, it is not possible to use poll(). Is there any poll() like function that I can use to detect a pin change of a GPIO?
EDIT: Just in case, if I am doing something wrong, here is my poll() usage that does not detect the pin change
struct pollfd pollfds;
int fd;
int nread, result;
pollfds.fd = open("/sys/class/gpio/gpio51/value", O_RDWR);
int timeout = 20000; /* Timeout in msec. */
char buffer[128];
if( pollfds.fd < 0 ){
printf(" failed to open gpio \n");
exit (1);
}
pollfds.events = POLLIN;
printf("fd opens..\n");
while (1)
{
result = poll (&pollfds, 0, timeout);
switch (result)
{
case 0:
printf ("timeout\n");
break;
case -1:
printf ("poll error \n");
exit (1);
default:
printf("something is happening..\n");
if (pollfds.revents & POLLIN)
{
nread = read (pollfds.fd, buffer, 8);
if (nread == 0) {
printf ("result:%d\n", nread);
exit (0);
} else {
buffer[nread] = 0;
printf ("read %d from gpio: %s", nread, buffer);
}
}
}
}
close(fd);
EDIT2: the code on https://developer.ridgerun.com/wiki/index.php/Gpio-int-test.c works fine with poll() I needed to define the rising/falling edge for the interrupt and a little bit fix on the definition. It solves my problem, however, it might be good for me and some other people to hear/know the alternative methods.
I have never seen this board before, however I guess PIC is fully implemented for this board (usually is like that) but you have to configure interrupt additionally in GPIO controller (usually is like that).
Some part should be done as a kernel module, then you have to pass information about interrupt to you application.
Example way to do this is to implement following thing as a kernel module:
setup GPIO controller to enable interrupt on particular port and level
(how to do this you can find here: http://cache.freescale.com/files/dsp/doc/ref_manual/IMX23RM.pdf 37.2.3.3 Input Interrupt Operation)
enable GPIO interrupt in PIC (how to do this: http://lwn.net/images/pdf/LDD3/ch10.pdf Chapter10)
implement interrupt handling routine (I will describe a little bit below)
implement ioctl interfaces for your module.
and a rest in your application:
a function that can coosomeoneperate with interrupt.
Simplest way of passing information about interrupt from kernel to app is by semaphore on kernel side.
in module you can implement an ioctl that will sleep until interrupt happen.
So application will call this ioctl and its thread will be blocked until interrupt happen.
Inside module, interrupt routine should check if application thread is now blocked, and if so up() semaphore.
EDIT*****
This CPU has SSP that has working mode for SPI. Why dont use it ??

SPI timeout in Linux and C

I'm trying to implement a timeout for some hardware transmissions, to add security to a big project. I already implemented timeout using select for UART transmission, but I don't know how to add a timeout in a SPI transmission.
This is my reading code:
int spi_read(int fd, char command, char* buffer, int size, int timeout)
{
struct spi_ioc_transfer xfer[2];
int status;
memset(buffer, 0, sizeof(buffer));
memset(xfer, 0, sizeof(xfer));
xfer[0].tx_buf = (unsigned int)(&command);
xfer[0].len = 1;
xfer[1].rx_buf = (unsigned int)buffer;
xfer[1].len = size;
status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer);
if(status < 0)
return NOERROR;
else
return EHWFAULT1;
}
It sends a byte sized command and receives a response of certain size (in half duplex mode). How can I implement a timeout in the response? Can it be implemented using select? Should I separe both transactions and use select or better use an alarm?
Then, I have the same question for a full duplex mode, which is implemented too using ioctl. Can you give me any hints?
In hardware the SPI master does not 'wait' for a response. By definition, the SPI master provides the clock cycles and the slave must reply. The concept of waiting for a response doesn't apply to the SPI bus. (I'm assuming you're operating the SPI master)
(deeper in the protocol, the SPI might poll the hardware to see if it's done/ready; but the SPI bus itself is getting an immediate answer every time).
To clarify: the SPI clocks in whatever is on the SPI MISO pin. Whatever level is on the MISO pin is the reply, even if the slave is not explicitly driving a level. The only way to detect a non responsive slave is to pullup/pulldown the MISO in a way that can not be interpreted as a valid message.

Correct initialization sequence for Linux serial port

I wrote an application that must use serial ports on Linux, especially ttyUSB ones. Reading and writing operations are performed with standard select()/read() loop and write(), and there is probably nothing wrong in them, but initialization code (or absence of some part of it) damages something in the tty subsystem. Here it is:
vuxboot(string filename, unsigned baud = B115200) : _debug(false) {
_fd = open(filename.c_str(), O_RDWR | O_NOCTTY);
if(_fd < 0) throw new io_error("cannot open port");
// Serial initialization was written with FTDI USB-to-serial converters
// in mind. Anyway, who wants to use non-8n1 protocol?
tcgetattr(_fd, &_termios);
termios tio = {0};
tio.c_iflag = IGNPAR;
tio.c_oflag = 0;
tio.c_cflag = baud | CLOCAL | CREAD | CS8;
tio.c_lflag = 0;
tcflush(_fd, TCIFLUSH);
tcsetattr(_fd, TCSANOW, &tio);
}
Another tcsetattr(_fd, TCSANOW, &_termios) sits in the destructor, but it is irrelevant.
With or without this termios initialization, strange things happen in system after the application exits. Sometimes plain cat (or hd) exits immediately printing nothing or same stuff each time, sometimes it is waiting and not displaying any of the data that is surely sent onto the port; and close() (read() too, but not every time) emits a strange WARNING to dmesg referring to usb-serial.c.
I checked the hardware and firmware tens of times (even on different machines) and I am sure it is working as intended; moreover, I stripped the firmware to just print same message over and over.
How can I use serial port without destroying anything? Thanks.
Hitting a WARN_ON line might mean that you've hit a kernel bug. I know that there has been much work on improving the USB-serial driver lately; I suggest trying a newer kernel, and/or asking on the linux-usb#vger.kernel.org mailing list.
I am not sure what is wrong with your snippet of code there but this might come in handy, if you haven't already seen it: Serial Programming Guide for POSIX Operating Systems
I had to do some serial port interfacing quite recently and this library worked fine, that might serve as another example.
Just as a side note really, your error check on open isn't quite right - error conditions are signalled by a return value of -1. (0 is a perfectly valid fd, usually connected to stdin.)
You might want to try:
vuxboot(string filename, unsigned baud = B115200) : _debug(false) {
_fd = open(filename.c_str(), O_RDWR | O_NOCTTY);
if(_fd < 0) throw new io_error("cannot open port");
// Serial initialization was written with FTDI USB-to-serial converters
// in mind. Anyway, who wants to use non-8n1 protocol?
tcgetattr(_fd, &_termios);
- termios tio;
+ termios tio;
+ memcpy(&tio, &_termios, sizeof(struct termios));
tio.c_iflag = IGNPAR;
tio.c_oflag = 0;
tio.c_cflag = baud | CLOCAL | CREAD | CS8;
tio.c_lflag = 0;
tcflush(_fd, TCIFLUSH);
tcsetattr(_fd, TCSANOW, &tio);
}
This makes it so that any unexpected fields of termios on your system get somewhat reasonable values.
Okay. This may not be a perfect solution... it definitely isn't. I just threw out FT232 converter (fried it, actually), and used CP2102-based one. It just works now (and also is 6 times cheaper).

Resources