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

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 (

Reply to
Jonathan Bosch
Loading thread data ...

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

Reply to
Jonathan Bosch

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

Reply to
Jonathan Bosch

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 (cbfalconer@yahoo.com) (cbfalconer@worldnet.att.net)
   Available for consulting/temporary embedded and systems.
 Click to see the full signature
Reply to
CBFalconer

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.

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

Reply to
Paul Keinanen

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

Reply to
Jonathan Bosch

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

formatting link

Peter

Reply to
moocowmoo

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

Reply to
Norm Dresner

"Jonathan Bosch" schreef in bericht news: snipped-for-privacy@easystreet.com...

Reply to
Frank Bemelman

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.

Mark Borgerson

Reply to
Mark Borgerson

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.
Reply to
Android Cat

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

Reply to
Jonathan Bosch

Thanks Peter,

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

Regards,

Jonathan Bosch

Reply to
Jonathan Bosch

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?

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)

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

Jonathan Bosch

Reply to
Jonathan Bosch

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

Reply to
Andras Tantos

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.

Reply to
Tom

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("baud=115200 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')

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

Reply to
Lewin A.R.W. Edwards

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.