Go to the first, previous, next, last section, table of contents.


L_buffer.h: a circular buffer for logging.

A traditional embedded systems trick is to log messages to a circular buffer in core. This has the following benefits:

  1. Speed -- writing to a in core buffer is much faster than spitting out messages to a file on disk. It is often fast enough to leave at least most of the messages in the final product.
  2. Field debugging -- what the ... was the user doing before the system crashed. Oh lets ask them, I'm sure they'll give us a good problem report.

Type: struct L_BUFFER
Used to define buffer variables, it is similar to `FILE*' type in `stdio.h'. To create an instance use `L_buffer_create'.

Function: L_BUFFER* L_buffer_create (size_t size)
Function: L_BUFFER* L_buffer_delete (L_BUFFER *b)
These are used to create or delete a buffer which can contain size characters.

  L_BUFFER *lbuffer;

  lbuffer = L_buffer_create(32*1024); /* create a 32K buffer */
  ...;
  L_buffer_delete(lbuffer); /* and delete it after use */

Function: void L_buffer_wraparound (L_BUFFER *b, int w)
A buffer created by `L_buffer_create' is set up so that the new messages will overwrite the older messages in the buffer. If you wish to disable this overwriting, e.g. to keep the first 32K bytes of your system startup messages you should use `L_buffer_wraparound'. For example:

  L_BUFFER *lb = L_buffer_create(32*1024);
  L_buffer_wraparound(lb, 0); /* disable wraparound */

Function: void L_buffer_printf (L_BUFFER *b, const char *fmt, ...)
Function: void L_buffer_puts (L_BUFFER *b, const char *str)
Function: void L_buffer_putchar (L_BUFFER *b, char ch)
These are the routines which do that actual printing to the buffer.

  L_buffer_printf(lbuffer, "U: user input %c\n", c);
  L_buffer_puts(lbuffer, "warning: its too hot");
  L_buffer_putchar(lbuffer, '*');

Note: a null pointer passed to the `L_buffer_puts' function prints as `(null)'. (7)

Function: void L_buffer_clear (L_BUFFER *b)
Clear the log, i.e. remove all messages and start again.

Function: void L_buffer_dump (L_BUFFER *b, FILE *fp)
Dump the contents of the log *b to the file descriptor *fp. Typically *fp would be `stderr'.

Note that this does not change the contents of the buffer. This is important since we may have a hardware or software problem part of the way through the dump operation and you don't want to loose anything.

To reset the buffer after a successful dump use `L_buffer_clear'.

The output of `L_buffer_dump' consists of a starting message followed by the contents of the log. If a character in the log is not printable we print it out in hex on a line by itself.

* L_buffer_dump =
log message
and another
* non-printable character 0x1
more log messages
* end of dump

You also need to be able to integrate these functions into your design. See `examples/ott.c' for a complicated example. Here we will provide a simplified version which implements a new logging macro called `LFAST' which does a `printf' to the `log_buffer'. If you want to have all messages going to a `L_BUFFER' then you can redefine `L_DEFAULT_HANDLER'.

/* project.h - the project wide include file */

#include <nana.h>
#include <L_buffer.h>

/* LFAST(char *, ...) - log a message to the log_buffer */
/*     ##f translates as the rest of the arguments to LFAST */

#define LFAST(f...) LHP(L_buffer_printf,log_buffer,##f)

extern L_BUFFER *log_buffer; /* the log buffer */

The main program merely creates the log_buffer and eventually calls `L_buffer_dump' to print out the buffer when the system dies.

/* main.c - initialise the system and start things */

#include <project.h>

L_BUFFER *log_buffer;

main() {
  log_buffer = L_buffer_create(16000); 
  if(log_buffer == NULL) { /* not enough store */
    ...
  }
  LFAST("system starting at %f\n", now());
  ...;
}

void fatal_error() { /* called on fatal errors */
  FILE *f = fopen("project.errors","w");
  L_buffer_dump(b, stderr); /* print log to stderr */
  L_buffer_dump(b, f); /* print log to file */
}


Go to the first, previous, next, last section, table of contents.