Date: Fri, 4 Nov 2005 01:19:22 -0600 (CST) Subject: firmware X-UID: 99 Unfortunately, there's not much to see again. The things that can go wrong with embedded systems are outside the experience of applications or systems programming. With conventional software development, typically the following assumptions are made: 1. hardware is trusted to work predictably 2. all computers operate on 16 bit words at least 3. compilers generate code that works on the computer platform 4. interfaces do not depend on internal state 5. failure is not silent This is not an exhaustive list. It is just what comes to mind. The hardware is much closer to the surface when writing microcontroller firmware. With a modern operating system and development environment, the hardware is abstracted behind many layers of software, even for a lot of kernel programming. With a microcontroller, the hardware always shows through. The two most mysterious issues: a. Subtle timing changes causes I/O ports to stop working. This can be as minor as a for loop iterating too long or reordering some conditional logic. b. Firmware seems very sensitive to compiler optimization. Hardware may depend on instructions occuring in a specific order. But traditional compiler optimization relies on reordering of instructions. I don't fully understand why some code I write does not work (or the converse, why other code does work - but there is a sense of aesthetics - in general, minimalist and elegant code seems to work - overengineered and bloated code does not). I'm lazy so haven't been checking the generated object code, just noting when some C code doesn't work. C as a language has 16 bit integers at least. So much in C relies on the int. But many microcontrollers have an 8 bit data bus and registers. So you need to be careful to avoid implicit conversions to ints. To get timing right, you can: 1. spend hours following paths of execution and counting clock cycles 2. use an oscilloscope and use tunable settings Option two is definitely the way to go. I'm relying on the oscilloscope to tell me when the firmware is wrong now. It would be nice to have a logic analyzer. The bit banging serial communications does work. A design rule that seems to emerge is the frame oriented protocol. As there is no clocking, the receiver must always do the work of finding the frame. This implies that the transmitter always sends complete frames that are easy for the receiver to interpret. It seems obvious to state this. But it has non-obvious implications in how code must be written when it must work in real-time (to generate pulses in software, I need to keep unpredictability down to the microsecond range). Sending commands to the microcontroller from a computer board is stable. Phase and frequency correct pulse width modulation for the drive motors is good. Bit banged pulse width modulation for the steering motor is good. The gyro is good (and now I know this $120 device really works). There's about another week for firmware (and I think that is a realistic assessment - I think I know what I'm doing now). The major milestone will be when the entire robot is assembled and all work is software. From then, my first priority will be to drive it under full remote control. So it will then be a very large RC car with bonded channel (spread spectrum 900 MHz and 2.4 GHz WiFi) digital comms with a laptop as a base station. I'm also sleeping a lot now. Work intruded again to force this. But it did so in a way that is in the end positive. My metric for progress now is minimizing time stuck on a problem. I find that by focusing on clear thinking, it is possible to avoid becoming stuck for very long. You wiggle out of it.