Recently, one of our production people noticed a slight idiosyncrasy with a mature product that has been shipping with no trouble for years. The design has an embedded controller that is capable of recording and playing back digitized speech messages. Under reproducible conditions, unlikely to occur in the real world, the message could repeat itself several times.
I knew of this issue when writing the embedded code years ago, but I brushed it off as unimportant because it was unlikely to happen. Besides, if it did, the consequences were just not that big a deal. But, in the interests of aesthetics -- and because I was a little bored at the time -- I decided to modify the code to remove the problem. The fix consisted of a simple, small piece of keyboard-scanning code that had to be added. It took 10 minutes to implement.
Unfortunately, my mod was nearly inert; it only partially fixed the problem. The repeating message could still be reproduced under some conditions. When dealing with a relatively complex fix, it is not so disconcerting when it doesn’t go as planned, but this was very simple. It should have worked. I put the hardware on an emulator running on my laptop to try to catch the point in the code where the error occurred. I could see what was happening, but I couldn’t offer an explanation as to why.
So, I threw a logic analyzer into the mix. To catch the error, I had to define pretty complicated trigger conditions. Condition A -- complicated on its own -- had to occur once, then condition B -- also complicated -- had to immediately follow and occur four times simultaneously. Then, the answer fell into my lap. As is often the case for my embedded designs, I doubled-up on some of the I/O lines to the (PIC16F505) controller. One line was used to control two different components.
One component needed the idle state of the line to be high, while the other required it to be low. This would not have been a problem if I managed it well. I didn’t. The control line was left high by one subroutine, but when another subroutine started up, it assumed the line would be low. This meant that I missed generating an all-important rising edge. The fix was super simple; just reset the line at the beginning of the second subroutine to zero.
In the interest of cost, engineers often double-up on I/O lines, giving them multiple functions, sometimes involving both input and output. In a perfect world, it would be nice to have one I/O line per function, but that’s a rare luxury. It does feel good to be efficient by saving resources, but it comes with the price of due diligence.
This entry was submitted by Jonathan Eckrich and edited by Rob Spiegel.
Jonathan Eckrich has been president of Adaptivation since 1998. Much of his job experience is with designing industrial (VME-based) computer systems. He holds a Master of Computer Engineering (1985) and a Bachelor of Computer Science (1982) from Iowa State University.
Tell us your experience in solving a knotty engineering problem. Send stories to Rob Spiegel for Sherlock Ohms.