Thread: Can Only Read From Serial Port in Function That Opened It

  1. #1
    Registered User HalNineThousand's Avatar
    Join Date
    Mar 2008
    Posts
    43

    Can Only Read From Serial Port in Function That Opened It

    I had this working, thanks to help in another thread, and now when I open the serial port for reading and writing, I can ONLY read from the serial port in the same function where I opened it.

    This is not all the code in the file, but I start with my variables:
    Code:
    //Seperate namespace to keep them invisible to other files
    	namespace {
    		bool isOpen = false;
    		int infd = 0, outfd = 0, lastread = 0;
    		unsigned long naptime = 100;
    		long BAUD = B115200;
    		long DATABITS = CS8;
    		long STOPBITS = 0;
    		long PARITYON = 0;
    		long PARITY = 0;
    
    // Default value: use the RS232 port
    		string serdev = "/dev/ttyS0";
    	}
    Then, in order of use (but almost reverse order of how they're in the file), I have a function to open the serial port as a file:
    Code:
    void openport() {
    
    	if (isOpen) return;
    	isOpen = true;
    	cout << "Opening port: " << serdev << endl;
    	infd = open(serdev.c_str(), O_RDWR | O_NOCTTY);
    	fcntl(infd, F_SETFL, 0);
    	setportattr(infd);
    //Open for output later (device doesn't work well using same FD for in and out!)
    // 	outfd = open(serdev.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
    // 	setportattr(outfd);
    	
    	if (infd == -1 || outfd == -1) {
    		if (infd == -1)
    			perror("Unable to open port for reading");
    		if (outfd == -1)
    			perror("Unable to open port for writing");
    		exit(1);
    	} else {
    		cout << "Port " << serdev << " has been opened. Input: " << infd << ", Output " << outfd << endl;
    	}
    //Test read the port from in this function -- always works and reads a byte
    	cout << "====>Attempting to read port: " << infd << endl;
    	char* buffx; int rdx;
    	rdx = read(infd, buffx, 1);
    	cout << "====>FD: " << infd << ", Read length: " << rdx << endl;
    //Call other routine to test read it from outside function - always fails, even
    //if the test above is removed, so it's not a matter of if there's no data
    	fakeread();
    	return;
    }
    I initialize the serial port parameters here:
    Code:
    void setportattr(int portfd) {
    
    	struct termios options;
    	
    	tcgetattr(portfd, &options);
    //Should never change, set at 115200
    	options.c_cflag |= BAUD;
    	options.c_cflag &= ~PARENB;
    	options.c_cflag &= ~CSTOPB;
    	options.c_cflag &= ~CSIZE;
    	options.c_cflag |= CS8;
    	options.c_cflag |= (CLOCAL | CREAD);
    	options.c_iflag |= (IXON | IXOFF | IXANY);
    	options.c_cflag &= ~CRTSCTS;
    	int rc = tcsetattr(portfd,TCSANOW ,&options);
    	cout << "FD: " << portfd << ", Attr return code: " << rc << endl;
    	return;
    }
    Setting attributes is always successful. I've also tried reading a byte from the file in this function. It's worked in some cases.

    Then there's the simple function to do another test read:
    Code:
    void fakeread() {
    	cout << "---->Attempting to read port: " << infd << endl;
    	char* buffy; int rdy;
    	rdy = read(infd, buffy, 1);
    	cout << "---->FD: " << infd << ", Read length: " << rdy << endl;
    	return;
    }
    If I put read() statements anywhere in the openport() function, it works, but once I move it out and into another function, it ALWAYS fails (but it has worked if it was in the setportattr() function, at the very end of that function).

    This was working perfectly this afternoon. I can't figure out what I did that might have changed it that much, but now I can only read from the device from within that function. The debugging output I've printed (statements are included in above samples) shows that it's using the right file descriptor.

    Is this something so bleeding obvious that I'm not seeing it?

    Thanks for any help on this!

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    In your read function, char* buffy is not initialized, so it's highly unlikely to point to memory that can be written to. Perhaps using a char buffy, and read(... &buffy ...)

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User HalNineThousand's Avatar
    Join Date
    Mar 2008
    Posts
    43
    That seems to make a difference. Believe it or not, what I had was originally copied from a tutorial on the web.

    It had worked like that previously in another function. Any idea why it was working before and stopped at some point?

    This leads to another question. When it was declared as char* buff (or char* buffx or buffy of buffz -- used different names in each function attempt), nothing was declaring how long buff was. Is that part of the problem? And is it possible to dynamically declare the length of char buff[] when the function is called depending on the number of characters requested to be read in?

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by HalNineThousand View Post
    That seems to make a difference. Believe it or not, what I had was originally copied from a tutorial on the web.

    It had worked like that previously in another function. Any idea why it was working before and stopped at some point?
    Because "undefined behaviour" (which writing to the address contained in an uninitialized variable is definitely an example of) is like running through a road-junction when the lights are red - you may get away with it sometimes, but at other times the police catches you, or a driver comming the other way hits your car. It's NEVER a good idea to do undefined behaviour, and writing to undefined pointers isn't one that is likely to work very often - even if it works to write to the location your pointer HAPPENS to have by coincidence, it's unlikely that the location is a good one for your data.

    This leads to another question. When it was declared as char* buff (or char* buffx or buffy of buffz -- used different names in each function attempt), nothing was declaring how long buff was. Is that part of the problem? And is it possible to dynamically declare the length of char buff[] when the function is called depending on the number of characters requested to be read in?
    In standard C, variable length arrays is not allowed - you have to use malloc to allocate your own memory [or use some estimation of how much data you want to receive at a time and use a fixed size array]. Just make sure whatever method you use, never give "read()" a bigger "size" than your buffer.

    Since serial ports are relatively slow, using a small fixed size buffer and then assembling the "entire packet" as you go along in some way is perfectly fine [e.g. allocate a bugger based on the packet content, dynamically grow a packet container as it fills up, or whatever method you prefer].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,412
    In standard C, variable length arrays is not allowed
    From what I understand, variable length arrays are a feature of C99, so they are allowed in standard C.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User HalNineThousand's Avatar
    Join Date
    Mar 2008
    Posts
    43
    Thanks! I didn't realize that not specifying a length for buff in the first case was leaving it as undefined -- especially since I had seen that in a tutorial! I know what you say about undefined behavior. I used Assembler back in the '80s on an Apple //e and lately I've been using Java, so I'm getting used to C++ being in-between where I can use a variable that isn't defined but should not.

    In this case, and I could change it, I'm only reading one character at a time because I have to evaluate each character to see if it starts a command string, give the length of that string, or is the checksum at the end of the string. (And, of course, I have to add the value of each byte in between to compute the checksum and I can either do that when it comes in or go through a 2nd loop with all the same objects.)

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Laserlight is of course right. C99, which is the "new" standard allows variables to be used as the size of arrays. As does C++ of the current ratified standard. However, according to the standard the value still needs to be a constant value. So you can have something like this:
    Code:
    int func(const int size)
    {
        char array[size];
    ...
    }
    but this is non-standard [some compilers do support it tho']:
    Code:
    int func()
    {
       int size;
       ...
       // do something to set size, e.g. read some user-input or such
       char array[size];
       ...
    }
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 17
    Last Post: 07-14-2009, 08:17 AM
  2. Compiling sample DarkGDK Program
    By Phyxashun in forum Game Programming
    Replies: 6
    Last Post: 01-27-2009, 03:07 AM
  3. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM
  4. Problem with string and serial port
    By collinm in forum C Programming
    Replies: 2
    Last Post: 03-23-2005, 10:19 AM
  5. read from and write to serial port
    By wazilian in forum Networking/Device Communication
    Replies: 3
    Last Post: 04-25-2004, 08:22 AM