avr-libc-corelib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Avr-libc-corelib] Error handling


From: Jan Waclawek
Subject: Re: [Avr-libc-corelib] Error handling
Date: Tue, 22 Sep 2009 10:35:46 +0200

>I would rather use errno than an new errno_corelib. With RTOS, one has
>to save errono for eatch context, thus with errno_corelib, one more
>integer(four bytes) on the stack.

Eh, pardon? Are we still talking AVRs, you know, 8-bit microcontrollers (stress 
on 'micro')? And avr-gcc, where int is - naturally - 2 bytes?
Even so - and regardless of what I think of appropriateness of an RTOS in 
8-bitters - I would never assign to an error flag more than a single byte.

And, I would assign a single byte for the WHOLE library, not a separate one for 
each of the "devices". The rationale is, that errors should NOT happen.


>usart_setBaudrate(target_baudrate,pourcentageError).... target baud
>rate not attainable with specified pourcentage error)
>and so on..

Well, not quite so.

If you write a function, which is of one-off character (usually happens at 
startup and not regularly during runtime) and its functionality expressly 
includes range-checking and similar (e.g. that's the purpose of specifying 
percentage error, isn't it), you anticipate it will return some indicator that 
the input values don't match the required constraint. That's not really what a 
run-time error constututes. In fact, if one of the purposes of such function is 
to check constraints, I would not call the returning value an "error" at all. 
And, I would separate this checking functionality from the actual setting of 
baudrate anyway, but that's my personal choice.

>Example spi_write.... spi is not enabled
>spi_write_non_blocking..... spi transfer already in progress

Well, maybe, but not quite. These again constitute more of a programmer's 
error, which should be avoided at compile time, rather than a "vis major" which 
must be checked and resolved runtime. If these things might happen - e.g. in 
the latter one, if spi write is not driven by interrupt - then the programmer 
shall test for spi idle before calling the spi_write, etc.

Think rather of buffer overflows (which still is a programmer's fault but 
sometimes hard to avoid), or framing error in UART reception (which is a true 
vis major). The user doesn't want an error to happen, and he might make 
conscious choices in the design to avoid it - but it still might happen, 
occasionally, maybe beyond of his control, or because of complexity of the 
program prevents him to exactly predict all possible timing constraints. 

But, checking for this error every time a function is called is usually 
superfluous, hence wasteful. I explained this in my first post.

Think a try-catch construction. Or a hardware error exception mechanism in 
processors. Or the "IOResult" function in BorlandPascal and its successors. 

----

Okay, some quick examples in pseudo-code. There's one, single, global, one-byte 
error variable corelib_errno, zeroed (or set to any other convenien default 
value meaning "no error") at startup.

void push_to_circular_buffer(value) {
  buffer[head] = value;
  advance(head);
  if (head == tail) {
    undo_advance(head);
    corelib_errno = ERROR_BUFFER_OVERFLOW;
  }
}

uint8_t receive_byte_from_uart(void) {
  // called when we already know there's a byte in UDR - either by checking for 
appropriate flag or this is used in interrupt
  if (framing_error) {
    corelib_errno = ERROR_UART_FRAMING_ERROR;
  } else if (overrun_error) {
    corelib_errno = ERROR_UART_OVERRUN_ERROR;
  }
  return UDR;
}


This results in the smallest possible code - a simple write to memory - and the 
smallest execution time - as it will execute only rarely, when the error 
happens - in contrast with returning an error value upon each call.

---

Now somebody might argue that this is too restrictive, and he might want to 
have a separate error variable for a module where he expects an error to occur 
regularly. We can provide both this and the default common one with something 
like:

1. in all files of some_module replace corelib_errno by SOME_MODULE_ERRNO

2. in some_module.h:
#if defined(SOME_MODULE_ERRNO)
  extern uint8_t SOME_MODULE_ERRNO
#else
  #define SOME_MODULE_ERRNO corelib_errno
#endif

3. instruct the user to define the custom error variable as a uint8_t and 
#define SOME_MODULE_ERRNO to this variable BEFORE #including some_module.h.


---

Just ideas.

JW




reply via email to

[Prev in Thread] Current Thread [Next in Thread]