Page 105 - The Art of Designing Embedded Systems
P. 105

92  THE  ART OF  DESIGNING EMBEDDED SYSTEMS


                       to some limit you’ve set. Estimate the total stack use, and then double or
                       triple the size. Use this as the limit.
                            Put the stack monitor into one or more frequently called ISRs. Jump
                       to a null routine, where a breakpoint is set, when the stack grows too big.
                            Be sure that the compare is “fuzzy.” The stack pointer will never ex-
                       actly match the limit.
                            By catching the problem before a complete crash, you can analyze
                       the stack’s contents to see what led up to the problem. You may see an
                       ISR being interrupted constantly (that is, a lot of the stack’s addresses be-
                       long to the ISR). This is a sure indication of code that’s too slow to keep
                       up  with  the  interrupt rate.  You  can’t  simply  leave  interrupts disabled
                       longer, as the system will start missing them. Optimize the algorithm and
                       the code in that ISR.


                           The Curse of Malloc( )

                            Since the stack is a source of trouble, it’s reasonable to be paranoid
                       and not allocate buffers and other sizable data structures as automatics.
                       Watch out! Malloc( ), a quite logical alternative, brings its own set of prob-
                       lems. A program that dynamically allocates and frees lots of memory-es-
                       pecially variably-sized blocks-will  fragment the heap. At some point it’s
                       quite possible to have lots of free heap space, but so fragmented that rnal-
                       loc( ) fails.
                            If  your code does not check the allocation routine’s return code to
                       detect this error, it will fail horribly. Of course, detecting the error will
                       also no doubt result in a horrible failure, but gives you the opportunity to
                       show an error code so you’ll have a chance of understanding and fixing the
                       problem.
                            If  you  chose  to  use  malloc(),  always check  the  return  value  and
                       safely crash (with diagnostic information) if it fails.
                            Garbage collection-which  compacts the heap from time to time-is
                       almost unknown in the embedded world. It’s one of Java’s strengths and
                       weaknesses, as the time spent compacting the heap generally shuts down
                       all tasking. Though there’s  lots of work going  on developing real-time
                       garbage collection, as of this writing there is no effective approach.
                            Sometimes an  RTOS  will  provide  alternative forms  of  malloc( ),
                       which let you specify which of several heaps to use. If you can constrain
                       your memory allocations to standard-sized blocks, and use one heap per
                       size, fragmentation won’t occur.
                            One option is to write a replacement function of  the form pmalloc
                       (heap-number).  You defined a number of heaps, each one of  which has a
   100   101   102   103   104   105   106   107   108   109   110