embedded device->rs232->XP (kinda OT)

Do you have a question? Post it now! No Registration Necessary

Translate This Thread From English to

Threaded View

A device I wrote code for a while back required a serial code download
from a Windows based download program.  I developed the Windows program
too, in Delphi. The device "acknowledges" each line of Intel hex with a
'.'  .  It all worked fine until trying to move it to XP. On a PC with a
'native' serial port running XP, the Windows program does not see the
'.'   It doesn't work using a usb -> serial setup either.

Here's a summary of the desperate poking at it that I have done so
far.....

I have run the cabling through a breakout box and can see the character
headed off to the PC with my scope.

I have changed the Windows program to disregard the '.' and send the
next line after a delay, and the the whole process completes without the
PC receiving even a single char. (should have seen over a thousand).
This is hokey, I can't leave it this way.

I minimalized the size of the receive buffer for the port on the PC.

Strange thing - If the XP machine is a laptop that has a serial port by
virtue of the fact that it is in a docking station, It works fine. (
this is what I am told, haven't seen this one)

Oh yeah, and I googled for any XP serial port info that looked like it
might apply.

THIS IS TEE_ING ME OFF AND GETTING IN MY WAY!!!!  I want to get back to
reading Lewin's book (<-Worth it!) and playing with more fun stuff!

Thanks for any suggestions,

Jonathan Bosch




Re: embedded device->rs232->XP (kinda OT)
Quoted text here. Click to load it

One more reason not to use XP.  You no longer have control over
the ports without various drivers, and then the timing is out of
control.

It smells similar to a problem I had years ago with uxing Xmodem
to connect to a mainframe.  The mainframe sent a line, which went
into a transmit buffer, and the process went to sleep.  The line
got transmitted, which woke the process up, and it then tried to
receive an acknowledgement.  This wake/receive process takes time,
and also depends on what else is going on in the system.

Meanwhile the micro receiving the Xmodem frame has gobbled it up,
and immediately sent an acknowledge.  This happens during the
receive dead time for the mainframe.

Similarly, if the mainframe is receiving, it sends an acknowledge
and switches to receive after a delay.  The micro doesn't delay,
so the first part of the transmitted frame is missed entirely.

The cure IIRC, at the micro end, was to insert a delay before or
after sending any acknowledge, depending on the transmission
direction.  These delays play havoc with the net transmission
rate, which is why windowed streaming protocols were developed,
such as Zmodem.

I don't know if it exists on XP, but W98 comes with HyperTerm,
which has Zmodem capabilities.  The protocol is well defined, and
public, and C source code for send and receive modules is
available.

--
Chuck F ( snipped-for-privacy@yahoo.com) ( snipped-for-privacy@worldnet.att.net)
   Available for consulting/temporary embedded and systems.
We've slightly trimmed the long signature. Click to see the full one.
Re: embedded device->rs232->XP (kinda OT)



Quoted text here. Click to load it

Thanks for the reply....

What you describe here is exactly what I was guessing was happening in
my case also, but with one puzzling complication in the theory.    The
first line of Intel hex is of a 'special' type (6), and contains data
that, if correct for the particular device, causes the flash to be
erased in preparation for the new code.  This step takes a couple of
seconds, and the 0x2e is sent after the erase.  All other 0x2e's are
sent immediately.   For the first line, XP should have been well rested
and ready for receipt of the char.

BTW,   I am running the transfer at 57600 and the same Delphi component
connected to the same device (for another part of the devices function)
transfers bi-directional packets fine, at 9600, on XP! Also, what I
forgot to mention , is that the micro device has been shipping for a
while now and changing the integral loader or the protocol  is not
possible.  The manufacturer was wanting to be able to send techs out to
the site to put in the 'last' version of software over earlier ones.

Failing any fix on the XP side, one idea might be to find a small
inexpensive, but better behaved device with serial capability to perform
the transfer. Is there such a device? quantity 50-100.

Thanks again,

Jonathan Bosch


Re: embedded device->rs232->XP (kinda OT)
On Sat, 04 Oct 2003 07:16:38 -0700, Jonathan Bosch

Quoted text here. Click to load it

How does the Delphi access the serial line ? By using direct port
access (and virtualized by the OS) or using OpenFile, ReadFile or
WriteFile calls ? If it does access using direct port access, the port
virtualisation may have failed.

Does the port work with any other programs ? Connect ports 2 and 3
together and use Hyperterminal etc. to check if the characters are
echoed.

Quoted text here. Click to load it

Is your device a proper RS-232 device with +/-12 V voltage levels or
some kind of  RS-232 look-alike with 0 .. +5 V voltage levels ? Many
laptops generate and accept not so standard RS-232 levels :-).

Paul


Re: embedded device->rs232->XP (kinda OT)



Quoted text here. Click to load it


Hi Paul, thanks for the reply.

Delphi access the port through the Win32 API.  A strange thing is that
another Delphi application I wrote for configuring the device using a
Windows GUI works fine, bi-directional, on XP,  but at 9600 baud.  The load
occurrs at 57600 and its on another one of the device's serial ports, but
the UART type is the same.  The voltage levels look fine, and it looks like
the problem is strictly with XP, laptop or desktop.  It all works fine on my
Win98 laptop and desktop!!!
Arghhhhh!

Thanks again,

Jonathan Bosch




Re: embedded device->rs232->XP (kinda OT)
Quoted text here. Click to load it
load
like
my
    A thought:  In Win98, a program could -- and many did (including
libraries from arrogant manufacturers like Borland) -- access the serial &
parallel ports directly.  In WinNT & descendents (Win2K & WinXP, so far),
every known hardware resource is virtualized and every program has to either
 go through the system device drivers -- or provide its own.
    I'm only a Windows serial port dilettante but I've done enough low level
programming in Windows in general and the first thing I'd try is to check
the speed issue by dropping the communications rate to, say 9600 baud;  I'm
not implying that it's likely to be the culprit, but it can't but help to
put that issue to rest.
    The second thing I'd do is to go through the Windows API descriptions
very carefully looking for WinNT/Win9x distinctions in the serial ports.
Beyond that, I'd check the buffered vs. unbuffered I/O issues and any
control line requirements for the WinNT-based API.   There are a few good
books out there about RS-232 programming with Windows;  if you want a
recommendation, e-mail me off-list.

    Norm



Re: embedded device->rs232->XP (kinda OT)
Quoted text here. Click to load it

You might want to test it again with exactly that serial port, that cable
and at 57600.  It's unlikely that it's as simple as a bad connector, but
you might as well check that the port/cable works first.

Make a list of what's different between the working and non-working code
and eliminate each one as the cause.

Infamous last words:  "But I didn't change anything ... except ..."  :^)

BTW:  You might want to check your computer's date/timezone setting.
Your post is:
Date: Sat, 04 Oct 2003 20:16:41 -0700
But you're replying to a post:
Date: Sun, 05 Oct 2003 10:37:32 +0300

If you're not violating the laws of causality, you might be suffering from
"Redmond Timezone Syndrome".

--
Ron Sharp.



Re: embedded device->rs232->XP (kinda OT)



Quoted text here. Click to load it

You're right, I should. (back to the obvious!) I am at least partially basing
my believe that its a universal problem because I first heard about it from
the people that I wrote the software for and then was able to immediately
verify it for myself.  A few strategies I have thought of  involve blowing the
dust from the old device side source code and making a few "one off" versions
of the code to test some theories. And, unfortunately the procedure for
putting in a new bootloader was convoluted and involves yet more stuff to blow
the dust off of.  Oh well, what was I going to do tonight anyway?

Quoted text here. Click to load it

I know, I have said it myself before.  I have learned that its a phrase best
kept to yourself, and is meaningful only to get to the "except" part.  I will
take your list approach, though. (again)

Quoted text here. Click to load it

Thanks,  Ron for the suggestions and encouragement. (and for the correct
time!)

Jonathan Bosch




Re: embedded device->rs232->XP (kinda OT)
Quoted text here. Click to load it

I'd rewrite the application to use the serial port components in Turbopower
Async Professional. You'll find it freely available from www.sourceforge.com

Peter



Re: embedded device->rs232->XP (kinda OT)



Quoted text here. Click to load it


Thanks Peter,

I grabbed the component you referred.  I am encouraged by how well thought out
and thorough the package looks.

Regards,

Jonathan Bosch



Re: embedded device->rs232->XP (kinda OT)
Quoted text here. Click to load it

Yes, I can imagine. But it has to be something silly. Thousands of XP
computers are receiving 'dots' through the serial port. You have seen
it on the oscilloscope, it is there. Nothing magic about a dot.

What is the parity on the sending side, and what is it on the receiving
XP machine? Are you catching errors, the ones that are detected/reported
by the win api calls? Take a deep breath, and look again. Use another
PC to send dots, with and without parity, odd/even, and see if you can
receive them in your XP machine. And don't worry, these problems are
always fixed in a couple of days at most, at an unexpected moment ;)

--
Thanks,
Frank Bemelman
We've slightly trimmed the long signature. Click to see the full one.
Re: embedded device->rs232->XP (kinda OT)



Quoted text here. Click to load it

I took a deep breath, mowed my lawn actually, and am ready to again make a
survey of the obvious. (Your suggestions included, thanks!)  I know what you
mean about how these problems resolve in due time and at an unexpected moment.
But it always seems like the problem you haven't solved yet will become one of
the great mysteries of the universe.

Thanks for the encoragement,

Jonathan Bosch




Re: embedded device->rs232->XP (kinda OT)
says...
Quoted text here. Click to load it

This may sound like a silly question---but I got bitten by this
once:   How are you determining whether the dots are received?
Are you waiting for them to display on the screen?

I have found that it takes quite a bit of care with Borland
C++ builder to display individual characters as they arrive----the
Borland components want to wait until the end of a line to display
the accumulated input.  Delphi may have the same problem.

I found it necessary at one time to show in incrementing received
character counter---as the output on the screen display was
arriving in fits and starts.
Quoted text here. Click to load it
Mark Borgerson



Re: embedded device->rs232->XP (kinda OT)



Quoted text here. Click to load it

Thanks Mark for the response,

To see *any* received characters I put a breakpoint in the data received event
for the component.  This was a strategy that worked when I was first getting
the Delphi loader program working when the environment was Win98.  It did take
some time for me to make my peace with displaying data in Delphi, though.

Thanks,

Jonathan


Re: embedded device->rs232->XP (kinda OT)
Quoted text here. Click to load it

An idea to test this issue: connect the RXD line of one serial port to the
RXD of another (i.e. receiving the same data on both ports). Hook up some
serial monitoring app (HyperTerm for example) on the second port and monitor
the incoming data there while running your app on the first serial port as
normal.

Also, as others' suggested: check for changes in the Windows API. I would
doubt but it might be the case that now XP will buffer all input until it
sees a CR\LF and starts emitting data only afterwards. You might - for
example - try to open the file (Windows uses file handles to communicate
with serial devices) in Binary mode instead of ASCII. I don't know how to do
that in Delphi though...

Regards,
Andras Tantos



Re: embedded device->rs232->XP (kinda OT)
Quoted text here. Click to load it

I've worked on a few projects using Windows serial routines (however I was
using VC++ and not Delphi) but I imagine the API calls are very simmilar.
Early on, I did run into several odd problems where things would work on one
PC with one version of Windows but not the other. I've figured out that you
need to do the following:
First, call GetCommState() to fill in all the fields in the DCB structure with
all their current values. This will fill in both the documented and
undocumented fields. Next, explictly fill in ALL the documented fields in the
DCB structure, I believe there's 24 of them, but do not touch any of the
"reserved" or undocumented fields. Don't assume that the "default" value
for any particular documented field is the one that you want! Now call
SetCommState() with the same DCB structure. Now do the same with the
COMMTIMEOUTS structure and call SetCommTimeouts().
If you're using any fancy stuff like event characters make sure to call the
obligatory SetCommMask() function as well. You can also call PurgeComm() if
required.

In my case, the problem was that I was only setting the baud rate, data bits,
and parity, without touching any of the other 21 parameters on the serial
port. In some cases these remaining parameters would take some kind of default
value, or they would keep their previous value, or they would use whatever was
set up in the control panel for that port. After I set all 24 values
explicitly, the same program would work on any PC with any version of Windows.

--Tom.

Re: embedded device->rs232->XP (kinda OT)
Hi Jonathan,

Firstly, thanks for the kind book comment ;)

Secondly: I encountered very similar problems when writing a serial
setup utility for an embedded product. It would work on some systems,
but on others it would just never receive any bytes from the serial
port, even though the bytes were demonstrably there (and we could
communicate with the device using Hyperterminal). Here below is the
Windows code (in C, but possibly helpful). I remember specific magic
surrounding the BuildCommDCB call, which is deprecated these days IIRC
(but still the only damn way to get the program to work).

/*

    Initialize serial comms on port COMx

    Returns 0 if product found, -1 if not found

*/

int WakeupProduct(int iPort)

{

    DCB dcbComProps;

    char c;

    char tmps[16];

    int i, fFound = 0;

    COMSTAT csState;

    DWORD dwError;



    sprintf(tmps,"\.\COM%d",iPort);

    hSerialPort = NULL;

    hSerialPort = CreateFile(tmps, GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);



    // If we couldn't open the desired port, quit

    if (hSerialPort == NULL)

        return -1;



    // set up our desired protocol

    memset(&dcbComProps,0,sizeof(dcbComProps));

    dcbComProps.DCBlength = sizeof(dcbComProps);

    BuildCommDCB("baud11%5200 parity=N data=8 stop=1", &dcbComProps);

    dcbComProps.fAbortOnError = 0;    // NEW

    SetCommState(hSerialPort, &dcbComProps);

    SetupComm(hSerialPort, 256, 256);



    ClearCommBreak(hSerialPort);

    ClearCommError(hSerialPort, &dwError, &csState);



    for (i=0;i<10 && !fFound;i++) {

        COM_Write_Char('\r');

        c = 0;

        while (!COM_Read_Char_Timeout((unsigned char *) &c, 100) && c!='>')
{ }



        // If we detected a command prompt from the device, we're good to
go!

        if (c == '>')

            fFound = -1;



        PurgeComm(hSerialPort, PURGE_RXCLEAR);

    }



    // If we didn't get a final '>' prompt (from Cmd> prompt) then this
probably isn't a known product, so die.

    if (!fFound) {

        CloseHandle(hSerialPort);

        return -1;    // error

    }



    return 0;

}



/*

    Read a character with timeout (in 100ths of a second)

    Returns nonzero if timeout expired

*/

int COM_Read_Char_Timeout(unsigned char *thechar, int timeout)

{

    DWORD readbytes = 0;

    clock_t ot;

    COMSTAT cs;

    DWORD errs;



    // get one character

    ot = clock();

    ClearCommError(hSerialPort, &errs, &cs);

    while (!cs.cbInQue && (clock() - ot < (timeout * CLK_TCK)/100)) {

        ClearCommError(hSerialPort, &errs, &cs);

        WrapperYieldCall();

    }



    if (cs.cbInQue)

        ReadFile(hSerialPort, thechar, 1, &readbytes, NULL);



    if (!readbytes)

        return -1; // timeout error



    return 0; // OK

}


/*

    Get a response string from the product (\n\r terminated)

    Returns a NULL string if there was a timeout, otherwise returns
buffer

*/

char *GetResponseString(char *buffer)

{

    char c, *p = buffer;



    c=0;

    while (!COM_Read_Char_Timeout((unsigned char *) &c, 500) && c!='\n'
&& c!='\r') {

        if (c >= 32 && c <= 127) {

            *p=c;

            p++;

            *p=0;

        }

    }

    

    // dump trailing \r

    if (c == '\n' || c == '\r') {

        COM_Read_Char_Timeout((unsigned char *) &c, 500);

    }

    else

        return NULL;



    return buffer;

}

Site Timeline