So I've been continuing to play around with AVR assembly and struggling to get things working. With my first full-time job underway, I've had limited time to devote to this hobby, and I don't have all of the tools that I should have to properly test my prototype systems. However, I still have had the nagging suspicion that I was approaching the development process the wrong way. I finally realized what was missing while listening to an episode of Elicia White's Making Embedded Systems podcast that discusses test-driven development (TDD) for embedded systems. At first, I simply refused to believe that TDD and bare-metal programs were compatible, but the more I thought about it, the more I understood that the process of modularizing your code and running each module one at a time in a specially-configured environment was almost exactly the same.
That podcast, though, only discussed the semantics of testing C programs, which are easily compiled for almost any platform out there (as long as there aren't any platform-specific elements in your program, which should be discouraged). Assembly programs, though, are the least portable of all. A stable hardware environment with debugging support or an architectural simulator is required. Fortunately, Simulavr is available for AVR programs (though it only supports a limited subset of all devices). In addition, its developers have implemented a nice Tcl interface for it, which makes the process of writing unit tests much easier.
I have started a simple project to implement and test the above concepts. The files can be found on GitHub. Downloading the files (as well as installing Tcl, Simulavr, and all of their prerequisites) and running 'make test' launches the testing process. As of this writing, it is still not completely functional due in part to the lack of documentation for the simulator interface, but some more experimentation should produce a system that is able to test individual assembly routines by providing arguments and testing outputs via core registers. If it becomes robust enough, I can hopefully merge it into my other projects to help with their development.
Sunday, April 13, 2014
Sunday, January 5, 2014
Update: AVR-LCD Assembly Project
Well, my holiday break has been mostly uneventful, besides the fact that I received a Raspberry Pi (Model A) as a gift, so I'm looking forward to getting into that soon. In the meantime, though, I've finally had the chance to dig back into the AVR-LCD assembly project.
After a couple weeks of on-and-off work, I'm pretty much at exactly the same place. Except that I've managed to switch the compiler to avr-gcc. Exciting! For a while, the conversion broke the code in ways that confounded me until I stopped being dumb and actually took a look at the listing produced by the compiler, which converts the register defines into plain hexadecimal. Apparently, avr-gcc doesn't do you the favor of subtracting the IO-memory-space-offset from special function register addresses used with IO-specific instructions while the Atmel compiler does. When using IN, OUT, SBI, CBI, etc., the _SFR_IO_ADDR() macro can be used to subtract the offset. Once that was inserted to all of the appropriate places, the program worked properly. Hello again, world!
The online avr-libc manual became a valuable resource for me during the conversion by providing code samples and a Makefile template. I also took some time to play around with Simulavr. Since that simulator only supports a limited number of AVR devices (not including the ATMega328P), I needed to make my assembly compatible with the ATMega328. Fortunately, all this required was replacing the CALL instructions with RCALL. With the help of this page, I was then able to put together a command to run the simulator and output a VCD file to verify the functionality. The command is recorded in a script that is up on the project's GitHub page (avr-gcc branch) along with the updated assembly source and Makefile.
After a couple weeks of on-and-off work, I'm pretty much at exactly the same place. Except that I've managed to switch the compiler to avr-gcc. Exciting! For a while, the conversion broke the code in ways that confounded me until I stopped being dumb and actually took a look at the listing produced by the compiler, which converts the register defines into plain hexadecimal. Apparently, avr-gcc doesn't do you the favor of subtracting the IO-memory-space-offset from special function register addresses used with IO-specific instructions while the Atmel compiler does. When using IN, OUT, SBI, CBI, etc., the _SFR_IO_ADDR() macro can be used to subtract the offset. Once that was inserted to all of the appropriate places, the program worked properly. Hello again, world!
The online avr-libc manual became a valuable resource for me during the conversion by providing code samples and a Makefile template. I also took some time to play around with Simulavr. Since that simulator only supports a limited number of AVR devices (not including the ATMega328P), I needed to make my assembly compatible with the ATMega328. Fortunately, all this required was replacing the CALL instructions with RCALL. With the help of this page, I was then able to put together a command to run the simulator and output a VCD file to verify the functionality. The command is recorded in a script that is up on the project's GitHub page (avr-gcc branch) along with the updated assembly source and Makefile.
Subscribe to:
Posts (Atom)