Issue with XBee AT command mode with PropGCC FDS
R
Posts: 5
I am using PropGCC to develop software that interacts with XBee Series 2 radios in AT (transparent) mode.
When my program first boots up it puts the XBee in command mode, then uses AT commands to echo configuration information back over stdout to the terminal.
My problem is that I seem to have to print a sacrficial character to the XBee after I read from the XBee serial, or else it doesn't work.
Here is a simplified part of my program that exhibits the behavior:
The fputc('x', ser) above is the sacrificial character I mentioned above.
The terminal output from this is:
My setup is:
Thanks for taking the time to read over this and any insight you might have.
When my program first boots up it puts the XBee in command mode, then uses AT commands to echo configuration information back over stdout to the terminal.
My problem is that I seem to have to print a sacrficial character to the XBee after I read from the XBee serial, or else it doesn't work.
Here is a simplified part of my program that exhibits the behavior:
#include <stdio.h> #include <propeller.h> #include <driver.h> extern _Driver _FullDuplexSerialDriver; _Driver *_driverlist[] = { &_FullDuplexSerialDriver, NULL }; // XBee line terminates with /r, not /n, so this is a re-implemented // fgets that also acknowledges /r char * rfgets(char *buf, int size, FILE *fp) { int c; int count = 0; --size; while (count < size) { c = fgetc(fp); printf("Saw %d '%c'\n", c, c); if (c < 0) break; if (c == '\n' || c == '\r') break; // Swapped this to drop line terminator buf[count++] = c; } buf[count] = 0; return (count > 0) ? buf : NULL; } int main (int argc, char* argv[]) { char serData[64]; char atsh[16]; char atsl[16]; FILE *ser; ser = fopen("FDS:115200,26,27", "r+"); if (ser == 0) { puts("FATAL: fopen(\"\n"); return 0; } // Make sure chars are available promptly from radio ser->_flag &= ~_IOCOOKED; setvbuf(ser, NULL, _IONBF, 0); memset(serData, 0, 64); memset(atsh, 0, 9); memset(atsl, 0, 9); waitcnt(CNT+CLKFREQ); // Make sure the line has been quiet in case a restart just occurred puts("Getting XBee config..."); fputs("+++", ser); puts("+++"); rfgets(serData, 64, ser); puts(serData); fputc('x', ser); // If this line is removed, the rfgets below never receives data fputs("ATSH\r", ser); puts("ATSH"); rfgets(atsh, 9, ser); puts(atsh); return 0; }
The fputc('x', ser) above is the sacrificial character I mentioned above.
The terminal output from this is:
Loading Controller.elf to hub memory 10700 bytes sent Verifying RAM ... OK [ Entering terminal mode. Type ESC or Control-C to exit. ] Getting XBee config... +++ Saw 79 'O' Saw 75 'K' 'aw 13 ' OK ATSH Saw 49 '1' Saw 51 '3' Saw 65 'A' Saw 50 '2' Saw 48 '0' Saw 48 '0' 'aw 13 ' 13A200With the fputc('x', ser) commented, I only get:
Loading Controller.elf to hub memory 10684 bytes sent Verifying RAM ... OK [ Entering terminal mode. Type ESC or Control-C to exit. ] Getting XBee config... +++ Saw 79 'O' Saw 75 'K' 'aw 13 ' OK ATSHNote the 'aw 13' is caused by the XBee just returning a /r (carriage return) with out a line feed, so that is the closing ' printed over the first character of Saw. Maybe this type of odd behavior is causing in issue in the FDS code?
My setup is:
- Ubuntu 12.04
- Propeller Professional Development Board
- XBee Series 2 radio
- PropGCC built from source (to get the _IONONBLOCK)
- propeller-elf-gcc -v reports: gcc version 4.6.1 (propellergcc_v0_3_5_1766)
Thanks for taking the time to read over this and any insight you might have.
Comments
[1] What's necessary to know is how the low-level library function handles buffering of the fopen'ed device - e.g. is there buffering, and if so, is it settable via a standard ioctl()? If there is buffering involved though then an fflush() is supposed to, er, flush it out.
-Tor
Is that a possible clue into what is going on?
It's generally easier and safer to have two separate handles for input and output (just like stdin and stdout are used to address the standard input/output, you would open "serin" for input and "serout" for output.
Also note that "puts" always appends a \n to the data it's sending, which may or may not be what you want -- I usually like to use fputs instead, since then I can explicitly specify exactly what's being sent.
Eric
It seems it was an fflush() issue after all! My initial attempt at dumping in an fflush() was just where I had to put the fputc('x', ser) hack in, if you look at the code this is after I've already gone from a write, to a read, then am going back to a write mode. Putting fflush() between every transition as Eric mentioned is exactly what I needed. Below is the updated code that works, for anyone else with a similar issue :
I added a few more write/read interactions from my actual use case to show that the serial line continues to behave nicely.
Here is the same code, albeit much cleaner and easier to read, with separate FILE's for reading and writing. This is tested and works the same as the prior solution.
BTW, I did put in some debug code to ensure that even though fopen() is called to FDS twice, only one additional cog is used. I've ommitted that code from here since it wasn't relevant.