LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Hardware > Linux - Embedded & Single-board computer
User Name
Password
Linux - Embedded & Single-board computer This forum is for the discussion of Linux on both embedded devices and single-board computers (such as the Raspberry Pi, BeagleBoard and PandaBoard). Discussions involving Arduino, plug computers and other micro-controller like devices are also welcome.

Notices


Reply
  Search this Thread
Old 01-06-2017, 12:03 PM   #1
gazroobari
LQ Newbie
 
Registered: Aug 2016
Posts: 8

Rep: Reputation: Disabled
Error 25 (Inappropriate ioctl for device) when setting up RS-485 config


Hi,

I have code similar to the following which I am trying to use to set up my serial port (/dev/ttyAPP1) for use as 2-wire RS-485:

Code:
#include <sys/ioctl.h>
#include <linux/serial.h>
... other includes ...

int fd;
struct serial_rs485 rs485config;

fd = open("/dev/ttyAPP1", O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd < 0)
{
    // Code to handle error
}
rs485config.flags |= SER_RS485_ENABLED;
if (ioctl(fd, TIOCSRS485, &rs485config) < 0)
{
    fprintf(stderr, "Failed to execute ioctl, error %d\n", errno);
}
// Now do write/read of serial device ...
The code is compiling OK, so presumably must be resolving links to the relevant ioctl reference TIOCSRS485 and to the rs485 conhfiguration structure. However, when the code executes, I'm getting:

Failed to execute ioctl, error 25

Environment is GNU/Linux 3.10.28 on armv5, ELDK v5.5. The UART in question (AUART1) is built into the Freescale CPU. I think that is the only extra info I can provide. Unfortunately, I've no real experience of Linux programming at or near the kernel level, so I have no idea why I'm getting the error 25, what it *really* means, and what I might be missing if anything (e.g. do I need a specific device driver, how do I know if my serial.h and ioctl.h headers are correct, how do I know if my Linux kernel is correctly configured, etc.).

I know for sure that /dev/ttyAPP1 is the correct filename for the port.

Sorry not to be able to add much more intelligence to this; my programming skills lie in Java, so if you do feel able to respond to me, please treat me as a newbie in this specific area and spell things out for me, if you'd be so kind (even if we have to take this one step at a time!).

Hoping someone out there can give me a helping hand.

Thanks
 
Old 01-06-2017, 01:40 PM   #2
blue_z
Member
 
Registered: Jul 2015
Location: USA
Distribution: Ubuntu, Lubuntu, Mint, custom embedded
Posts: 104

Rep: Reputation: Disabled
> I know for sure that /dev/ttyAPP1 is the correct filename for the port.

You need to double check that.
The error number 25 is ENOTTY, or "Not a typewriter", e.g. not a serial terminal device.

The error number 25 is also a substitute for ENOIOCTLCMD, "No ioctl command".
Your effort to use this ioctl could be futile because it may not be implemented in that driver.
There are scores of serial port drivers in the Linux kernel, but only a few supported that RS-485 API before kernel version 3.19.

Examine the boot log to get the name of the serial port driver (perhaps mxs-auart).
Then examine the driver source code to confirm the existence (or not) of the RS-485 feature.
FWIW in 3.10 mainline, only atmel_serial, crisv10 (ETRAX), and mfc (Freescale Coldfire) have that RS-485 support.

Last edited by blue_z; 01-06-2017 at 04:19 PM.
 
Old 01-08-2017, 03:58 PM   #3
gazroobari
LQ Newbie
 
Registered: Aug 2016
Posts: 8

Original Poster
Rep: Reputation: Disabled
@blue_z

Just wanted to say thanks for the response.

The reason I say /dev/ttyAPP1 is the correct device needs a little explanation.

The previous code that was handling the 2-wire RS-485 traffic on this port was working of a fashion -- but unreliably (not written by me!). Our controller allocates two specific GPIO pins as responsible for enabling/disabling the line transmitter & receiver. The logical steps of the previous write() routine used were as follows:

a - Disable line receiver
b - Enable line transmitter
c - Do the writing
d - Disable line transmitter
e - Enable line receiver (so port can now receive)

However, I noticed that a good half of the packets (only about 8-byte Modbus messages) that we wrote weren't being responded to correctly. we put the device on an oscilloscope and noticed that, in this routine, the turnaround of the line was nowhere near instantaneous (but certainly should be). There would often be upto 10ms delays whilst waiting for the turnaround either before or after writing data; during these delays, the remote device would start responding to our write() before we were ready to receive. Thus the bit train we received would be corrupted quite often.

When I put these findings to another couple members of my team, they were pretty sure they could see the issue straight away: in steps a, b, d & e, we were flipping the GPIO pins by opening a file descriptor to '/sys/class/gpio/gpioXXX/value' and then writing a 0 or 1 to it (as appropriate). Functionally that is correct, but it appears that, some of the time, the kernel is busy doing other work and so there's a delay returning from those steps. They hold that the turnaround of the lines should take place much closer to the kernel, and the accepted wisdom is to do this by using the ioctl rs485 memory structure & calls. Hope this all makes sense ?

So now you can see why & how I've attempted to fix it -- except that we've gone from poorly working comms to none at all! However, the unreliable comms was definitely using /dev/ttyAPP1 so the device name is correct in that sense -- although I appreciate what you are suggesting about the device driver quite probably not recognising the ioctl call, and/or /dev/ttyAPP1 not being recognised as a TTY device. In my previous post I only stated the description of error 25 based on what perror() gave me; understand what you say about the ambiguity.

Incidentally, if I understand the electronics correctly (and I'm not experienced in that area), there is usually both a UART on-board the CPU as well as a separate line driver chip for converting signals into those suitable for 232 and 485 usage. Is that correct ? If so, I think the line driver in our case is based on the Linear Tech Corp 2870 chip. Don't know if that helps.

If I do manage to ascertain which serial driver is in use, where am I likely to find the source code for it ?

Thanks.
 
Old 01-08-2017, 08:57 PM   #4
blue_z
Member
 
Registered: Jul 2015
Location: USA
Distribution: Ubuntu, Lubuntu, Mint, custom embedded
Posts: 104

Rep: Reputation: Disabled
Quote:
Originally Posted by gazroobari View Post
They hold that the turnaround of the lines should take place much closer to the kernel, and the accepted wisdom is to do this by using the ioctl rs485 memory structure & calls. Hope this all makes sense ?
Yes, and I agree with that wisdom.
The gotcha is that the serial port driver is probably going to require enhancement to provide this feature.

Quote:
Originally Posted by gazroobari View Post
In my previous post I only stated the description of error 25 based on what perror() gave me; understand what you say about the ambiguity.
The initial reason for for doubting that device name was that I have never encountered it after several years of reading various forums.
If you had code that did a tcgetattr() and tcsetattr() sucessfully before trying the ioctl(), then one meaning of ENOTTY is eliminated.
After looking at the mxs-auart.c driver, your claim is obviously valid, but left the comment for completeness since errno 25 is used for several reasons.

Quote:
Originally Posted by gazroobari View Post
there is usually both a UART on-board the CPU ...
[Nit] The CPU and UART (plus other peripherals) are integrated into an SoC.
Quote:
Originally Posted by gazroobari View Post
... as well as a separate line driver chip for converting signals into those suitable for 232 and 485 usage. Is that correct ?
Correct. Your GPIOs (or the RTS control pin if the UART has one) connect to either this RS-485 line driver or (additional) gates for directional control.
Independent receive and transmit controls are not common (for half-duplex operation), but could be beneficial.

Since direction control of a half-duplex RS-485 port is typically by the RTS pin of the UART/USART, the use of two GPIOs is not conventional, and therefore should not be assumed to be supported by a device driver. Someone should have questioned how this generic interface was going to work for a specific (i.e. your) board.
E.G. the atmel_serial.c and mcf.c RS-485 implementations require that the RTS pin of the UART/USART control the direction. You cannot assign an arbitrary GPIO pin with these drivers.
The "accepted wisdom" did not think this through.

FWIW the 4.7 version of mxs-auart.c has definitions for RS-485 and multidrop features of the UART (e.g. either RTS or DTR is used for direction control), but does not seem to use them nor support the updated TIOCSRS485 interface.

Quote:
Originally Posted by gazroobari View Post
If I do manage to ascertain which serial driver is in use, where am I likely to find the source code for it ?
The 3.10.xx kernel that you're using is probably a BSP version for whatever reference design that your board is based on.
You mention "ELDK v5.5", which could be from Wolfgang Denk's site.
One of your teammates should be able to provide a more accurate answer.

Regards
 
1 members found this post helpful.
Old 01-09-2017, 06:14 AM   #5
gazroobari
LQ Newbie
 
Registered: Aug 2016
Posts: 8

Original Poster
Rep: Reputation: Disabled
Thanks again.

Spoken to a colleague and I think we are much closer to knowing what we need to do.

Turns out our CPU is iMX28 and the serial driver is mxs-auart.c (for ttyAPP0 thru' ttyAPP2). We do indeed need to add the RS-485 support to that ourselves, as you pointed out, and my colleague is fairly clear what needs coding. In fact he found a patch:

https://community.nxp.com/thread/321357

The patch in all probability is for a different version of the driver than we have but he is happy enough to do a diff, apply the changes & rebuild.

Our hardware guy is also involved. He wondered if the serial driver would be difficult to modify but we will see. He accepts that RTS is the way to go for line control rather than switching GPIOs. There's also talk of a temporary workaround to set the GPIO 'driver enable' pin to input and adding a wire link to RTS.

Anyway, with a bit of hard work hopefully we are on the way to resolving this properly.

Once again, blue_z, totally appreciate your assistance.
 
Old 01-09-2017, 07:36 PM   #6
blue_z
Member
 
Registered: Jul 2015
Location: USA
Distribution: Ubuntu, Lubuntu, Mint, custom embedded
Posts: 104

Rep: Reputation: Disabled
Quote:
Originally Posted by gazroobari View Post
He accepts that RTS is the way to go for line control rather than switching GPIOs.
If this involves a board change, then IMO there's not a compelling reason to change.
A quick look at i.MX28 documentation indicates that the AUART does not have hardware support for RS-485.
Whereas the Atmel USARTs do have hardware support for RS-485 that specifically involves the RTS pin.

Since the AUART does not have HW support for RS-485, then IMO you are free to depart from convention, and use any pin(s) to control the transceiver/gates.

Regards
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Weird Perl error with "Inappropriate ioctl for device" bnutting Programming 9 03-12-2012 07:25 AM
[SOLVED] Error no 25: Inappropriate ioctl for device for RTC cruiser Linux - Software 1 10-16-2011 11:13 PM
inappropriate ioctl for device praetorrian Linux - Software 1 05-09-2006 12:11 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Hardware > Linux - Embedded & Single-board computer

All times are GMT -5. The time now is 07:45 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration