LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Hardware (https://www.linuxquestions.org/questions/linux-hardware-18/)
-   -   USB serial port problem - ioctl of certain pins does not match termios defines (https://www.linuxquestions.org/questions/linux-hardware-18/usb-serial-port-problem-ioctl-of-certain-pins-does-not-match-termios-defines-4175608029/)

Krupski 06-16-2017 12:01 PM

USB serial port problem - ioctl of certain pins does not match termios defines
 
Hi all,

I'm not sure if this is a hardware problem or a software problem. If it's in the wrong forum, apologies and mods please move it.

First, hardware & software involved:
  • OS: Debian 8 x86_64
  • GCC: 4.9.2
  • USB <=> Serial: Both FTDI FT232RL and Cypress CY7C65213
I wrote a small C program to open the serial port and send data to a VFD (vacuum florescent display) that has a serial input (at 115200 baud). The code and the display work fine - I can send data to the display and view it. The serial port is setup to use hardware handshaking.

The display has a line called "SBUSY" that goes high when the display is busy, and I have this tied to CTS so that the serial stream is automatically stopped when the VFD is busy - works like a charm.

The VFD has a hardware reset input (active low) which I wanted to use. So I connected it to the DTR line of the USB interface and at program start I pull DTR low for 5 msec, then bring it back high to hard reset the VFD - also works fine.

Now (finally) the problem: When hard reset, the VFD asserts "SBUSY" immediately and it remains asserted after reset is de-asserted for a max of 100 msec (says the datasheet). In reality it stays asserted for about 50 msec (says my scope).

Since "SBUSY" is connected to CTS, I wanted to read CTS in a timeout loop to wait until the reset sequence was finished. I used this simple loop:

Code:

int busywait (int fd)
{
    int status;
    int timeout = 500; // give up after about 1/2 sec
    // note "fd" is a previously opened serial port
    while (timeout--) {
        ioctl (fd, TIOCMGET, &status);
        if ((status & TIOCM_CTS) == 0) {
            return fd; // reset done, return happy
        }
        usleep (1e3 * 1); // 1 msec
    }
    return -1; // timed out, return sad
}

Problem is, it doesn't work. After a lot of hair tearing, I decided to look at the raw HEX value of "status" and see if anything was changing (especially after about 50 msec). I found out that there was a bit changing, but the bit is TIOCM_CD (carrier detect!) rather than TIOCM_CTS (clear to send - which is what sbusy is connected to).

What the heck? Is there an error in the termios.h file, or am I doing something wrong? The SAME thing happens with either the FDTI based interface or the Cypress based board. I don't have a "real" (motherboard) hardware COM port to check, but I suspect it would do the same thing.

Any ideas will be greatly appreciated!

business_kid 06-18-2017 05:58 AM

Non standard behaviour from hardware doesn't surprise me in the least. Back in the day of the Via MPV3 chipset they disabled 2 crazy usb ports in later chip versions (mine had 6, later ones only had 4) and ehci_hcd was patched to cope with crazy stuff from non compliant usb ports. I gather you want the thing to work with your hardware, not a "100% standard compliant" piece of hardware (If such exists).

Never mind the manual, or the standard; make it work on your hardware - that's my advice. If you plan on selling/manufacturing, do a major rethink.

Krupski 06-18-2017 11:25 AM

Quote:

Originally Posted by business_kid (Post 5723999)
Non standard behaviour from hardware doesn't surprise me in the least. Back in the day of the Via MPV3 chipset they disabled 2 crazy usb ports in later chip versions (mine had 6, later ones only had 4) and ehci_hcd was patched to cope with crazy stuff from non compliant usb ports. I gather you want the thing to work with your hardware, not a "100% standard compliant" piece of hardware (If such exists).

Never mind the manual, or the standard; make it work on your hardware - that's my advice. If you plan on selling/manufacturing, do a major rethink.

Thanks for the reply, and no I'm not going to be selling it (it's a personal hobby project - actually I want to add a live display to my Linux based home media file server to see at a glance things like free RAID space remaining, CPU temperature, CPU usage, network bandwidth usage, etc...).

I know manufacturers disable features in products for various reasons. For example, odd sized hard drives (like a 3 TB) are actually 4 TB drives with a failed platter. Or, a "Model 950" video card with lower specs is the same as a "Model 990" video card except that part of the GPU chip is "roped off" due to fab defects. Or a "2 GHz CPU" is a die from the 4 GHz fab run that doesn't meet thermal specs at full speed. Or a "One port interface" is the same chip (die) as a "Two port interface" except that part of the die has a defect and is disabled.

This is even done INTENTIONALLY to make more profit. A higher end card with "two ports" sells for more than the card that has "one port", but uses the exact same interface chip, just with 1/2 of it either disabled in firmware or simply not connected.

Anyway, what you say would normally make sense... except that I get the EXACT same behavior from two totally different serial chips (FTDI and Cypress).

It seems rather unlikely that two different companies would do differently the exact same thing... which is why I suspect(ed) that the mistake is on my end.

business_kid 06-19-2017 04:51 AM

Back in the day, Amdahl used to do likewise with their mainframes. They had ~11 CPU boards, which had all the ram onboard, but only some connected (with a maze of measured wires on the back). You could pay for extra ram, in which case Amdahl took the CPU board back to the factory, and added a few more wires, and bingo, your ram was active.

Can't you use the signal on /CTS, or wherever it appears? If not, why not?

Krupski 06-19-2017 11:43 AM

Quote:

Originally Posted by business_kid (Post 5724255)
Can't you use the signal on /CTS, or wherever it appears? If not, why not?

Sure. Not only does CTS automatically throttle the serial comm via hardware handshake, I can also read it's state. The only problem is (which is what I was asking about) is that masking the return status with TIOCM_CTS doesn't work but using TIOCM_CD (carrier detect) does work.

In other words, the CTS pin is being seen, in software, as the CD pin.

Now, the problem can be EITHER the serial chip has an error internally (unlikely since two totally different chips do the same thing) OR there is an error in the software.

Considering the latter then, the error must be EITHER that the bit defines provided by GCC are wrong (again, unlikely) or else I (as the programmer) am doing something wrong.

Removing all of the unlikely possibilities, all that's left is that I must be doing something wrong.

I know I could just say "heck with it - it works - use it", but as the thug in Dirty Harry asks right after Harry says the famous line "...do ya feel lucky? ...well do ya... punk?", "I just gots ta know" :)

business_kid 06-19-2017 01:52 PM

I think you do know. The standard seems out of sync with the chips. You can break the rules, and nobody will know unless you tell them. Add a sneaky diode or miswire and test your program that way. Personally, I would modify the program.

All those CTS, CD, etc are rarely used these days, as most serial lines just connect 2,3, &5 (from memory) = receive, transmit, & earth. Your RS232 chip is a few gates in a corner of some massive asic - poorly tested, no doubt.

AwesomeMachine 06-19-2017 03:26 PM

I had a problem with USB-serial converters and use on serial bench DMMs. Obviously, serial has more pins than USB, so the converters do switching to account for more pins. I don't think there are any USB adapters that are fully serial compatible.

Most, if not all, of the adapters do not enable all 9 pins. US Converters are some of the best I know. But even those are not 100% serial compatible.


All times are GMT -5. The time now is 07:31 AM.