Serial driver error handling

Hi:

Once again, I am writing a buffered, interrupt-driven driver for the serial comm UART (SCI) in the TI TMS320F2812. The lowest level interface to the user will be a function

int SCI_getc(void);

returns the next character received or EOF if nothing is available.

However, if there is an error in the receiver, there appear to be two ways to inform the user space:

  1. On the call to SCI_getc() after all valid chars have been removed from the buffer, return a special code other than EOF, such as a:

#define SCI_RXERR -2 /* or something like that */

Now if detailed info on the nature of the error were needed in this case, a call such as SCI_status() could provide this. In this case, the user mustn't always call SCI_status() after an EOF to find out if it was really no char available, or an error.

Since serial reception fundamentally differs from file IO, I find this option attractive.

  1. The second option is to return EOF always if there is no char available or there is an error, similar to fgetc(). Then the user would have to call another function SCI_status() or the like to get a code which can be parsed to determine the specific nature of the error.

Since the SCIx_getc() call will frequently return EOF while waiting for data, it seems cumbersome to always have to call SCI_status() to see if it was due to an error.

What is typically done?

Thanks for input.

--
Good day!

____________________________________
 Click to see the full signature
Reply to
Chris Carlen
Loading thread data ...

Note this also requires that your returned value be larger than a char, a failing shared by the C character level input fuctions.

Option 3. Ignore them except as needed to clear them from the hardware (and maybe collect stats). Leaving error check up to higher level protocols.

Option 3 is certainly common, I won't call it typical. There's often little to be gained by error checking at the individual byte level.

Robert

** Posted from
formatting link
**
Reply to
Robert Adsett

On Tue, 10 Jun 2008 19:50:34 -0400, Robert Adsett wrote in comp.arch.embedded:

Well, yes and no. The 2812 does not have 8-bit bytes, CHAR_BIT is 16. sizeof(int) == sizeof(char) == 1.

But the SCI is an 8-bit peripheral. All reads from the SCI Rx data register return some value in the low 8 bits, and zeros in the high 8 bits.

So one can easily pick patterns above 255 to use for any special purpose indicators.

--
Jack Klein
Home: http://JK-Technology.Com
 Click to see the full signature
Reply to
Jack Klein

On Tue, 10 Jun 2008 15:59:32 -0700, Chris Carlen wrote in comp.arch.embedded:

You may have to decide if EOF is optimum. You are using in a way that is different than in C FILE * operations. Your caller could receive EOF now, and without doing anything he can receive a valid data value if a character has been received since then. That doesn't happen in C streams.

You do realize that the SCI is an 8-bit peripheral on an architecture with 16-bit registers, don't you? No data value read from the UART will ever be outside the range of 0 to 255. That leaves you an enormous number of values to define as various status indicators, rather than data.

Consider something like:

enum { SCI_NO_DATA = 0x100, SCI_PARITY_ERROR = 0x101, SCI_OVERFLOW_ERROR = 0x102, SCI_FRAMING_ERROR = 0x103, SCI_BREAK_RECEIVED = 0x104 /* continue as needed */ };

This enumeration is defined in a header that includes the prototypes of API functions.

Then your user merely has to do:

int val = SCI_Get(); if (val < SCI_NO_DATA) { /* do something with data */ } else { /* handle errors, perhaps with a switch on the enum value */ }

--
Jack Klein
Home: http://JK-Technology.Com
 Click to see the full signature
Reply to
Jack Klein

Missed that part.

Robert

** Posted from
formatting link
**
Reply to
Robert Adsett

Yes. In discussions with our main programmer here (I am mainly an electronics and laser/optics guy, but also like to do low-level programming) he mentions that most programmers tend to agree that serial IO doesn't fit the C stream model well, mainly since the serial port may have nothing available at times, which doesn't mean that it is the end of file.

We also got into a discussion of different models for the operation of a SCI_getc() like function. I was designing my function to not block, but just return EOF as a "nothing available" indicator. It would be up to higher level code (the protocol level) to determine the significance of this.

He tends to think the SCI_getc() call *should* block until something is available to return, or timeout and then return an EOF, in which case EOF has a somewhat different significance than in the non-blocking case.

I like the non-blocking timeout model since my usage might be listening to human types commands at a terminal, for which it is impossible to define a timeout. What if the guy/gal takes their lunch break in the middle of typing a command?

Yes, though actually it has 32 bit registers; but at most 16 bit IO registers, granted. The char type is defined identical to int, so one can't really work with 8 bit bytes, and reads from 8 bit registers automatically "cast" to ints. That is why my first option shown above is to use the upper byte range for an error code. This isn't really afforded by the architecture though. It is simply a choice of how to define the return value of the function.

The gist of my question was mainly to determine if the mood among programmers was such that deviations from some standard model are looked down upon, and also to see if there is any sense of standardization of APIs to talk to UARTs at all, at the embedded device level. This doesn't appear to be the case, which encourages me to do something exactly like I mentioned and you detail below...

Yes, exactly.

--
Good day!

____________________________________
 Click to see the full signature
Reply to
Chris Carlen

I'd suggest taking a look at how Unix non-blocking I/O works - the ideas there have been well tested with real world experience. There you have two functions for dealing with reading data. read() functions as you would expect, however if there is no data available it returns -1 - not EOF (even though these are the same thing, conceptually there is a difference). errno is set to indicate why

-1 was returned, so you have different codes for EOF, no data, hardware error etc.

Applying these concepts to your situation that suggests two distinct functions - your SCI_getc() function like you have now, probably in 'non-blocking' trim, and an SCI_poll() function that tells you how many characters are available to be read. Alternatively, SCI_poll() could simply have a boolean sense, telling you if there is any input waiting to be read. This approach has the merit that you can test for the presence of input in a completely different area of code to where you actually read it, so for example you can have such a test in your program main loop and only call your 'process input' stuff when it is actually needed.

--
Andrew Smallshaw
andrews@sdf.lonestar.org
Reply to
Andrew Smallshaw

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.