So far, despite working on a variety of bare-metal software features for the Raspberry Pi, I have not managed to achieve my aim of using the principles of TDD (Test-Driven Development). In my "day job" I make a lot of use of TDD techniques, and I am convinced that this approach both greatly improves the quality of the code and de-stresses the development process. Before I go much further along the path of building an experimental operating system and its system language, I want to get my development environment set up for use with TDD.
Effective TDD needs a close connection between source code and its unit tests. The development cycle of "Red, Green, Refactor" requires that running tests be fast and simple enough to do every few minutes, and that the results of tests lead directly to the code for the test so it can be implemented, fixed, or refactored. These needs are very hard to meet with traditional cross-compilation for embedded systems, so I propose to architect my system so the bulk of it can be built and tested quickly and easily on the development machine, with only the smallest, most hardware dependent part of the system needing to be tested on the real hardware.
To make this work, I need two things. The first is for the software I'm building to be arranged so that the machine dependent parts are identifiably separate from the rest which can be built and tested locally. The second is the availability of two compatible toolchains: one for the target machine and one for the development box, and a way of building, linking and testing the appropriate sections of the code.
The first step in this process is to add some extra folders ('generic', 'emulated', and 'stubs') alongside the existing 'raspi' folder. Move what generic code we have so far (currently just main.c and morse.c, but some of the higher-level uart code will follow if this works) to 'generic', and adjust the makefile to build code from both 'generic' and 'raspi' folders.
MODULES := raspi generic
This can be tested by removing any lingering .o files etc.then make clean and make. Pop the resulting img file on the card and check that it still works.
Now on to the more tricky stuff. I'm developing on Windows at the moment. Not my favourite platform, but this machine is not quite hunky enough to run a decent Linux development environment in a VM. The ARM code for the Raspberry Pi is built with the yagarto toolchain, a port of the GCC toolchain to this particular target architecture. For the best compatibility building locally, we need a local port of the GCC tools. On windows the choices seem to be MinGW or cygwin. The main benefit of cygwin seems to be its Linux/Posix compatible libraries, but as I don't plan to use any of these libraries in my system code, I thought I'd go with the somewhat simpler MinGW. If this doesn't work, I'm sure I can change my mind later.
Installing MinGW was pretty straightforward - download an installer and let it do its stuff. I chose to install under C\devtools, which is where I had also put yagarto.
A quick check at the MobaXterm command line lets me run /drives/c/devtools/MinGW/bin/gcc --version to show
gcc.exe (GCC) 4.7.2 Copyright (C) 2012 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Having a compiler available was one thing, but having an effective makefile setup and directory structure to build several different versions of the code (and to avoid getting confused and inadvertently combining object files created for different target architectures) is another thing entirely. having got the MingW toolchain installed I then left this for a bit while I tried to think of how best to achieve this. During that time I was writing a bit of different C code on a Linux VM on my laptop. When I came back to this desktop dev box I naturally picked up the code to finish it off. It wasn't until several compile and run cycles later that I realized that (a) I was building the code using make and gcc and running it on Windows with no problems, and (b) I had never got around to adding MingW to my PATH. SO how come it was working?
It turns out that I had been smarter than I thought. Back before Christmas, I wrote about development tools including MobaXterm and its selection of plugins. When I installed MobaXterm, I added the git plugin, but also the Gcc, G++ and development tools plugin. Because I was used to running my Raspberry Pi cross compilations from the MobaXterm console, I had just picked up there with the new code. Looks like I had a WIndows gcc toolchain installed al lalong, and I never needed to bother installing MingW. D'oh!
In actuality, it is a slightly older version of the compiler, gcc --version gave
gcc (GCC) 4.3.4 20090804 (release) 1 Copyright (C) 2008 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
That hardly matters to me. All I plan to use is the basic core of the language, so I can be sure of maximum compatibility between code running on the two systems.
This does increase my admiration for MobaXterm even more. Installing the gcc toolchain plugin was so easy I forgot I had done it. In comparison even the relatively straightforward MingW installation seemed complicated!
I'm still not set up for unit test builds yet though, so that will have to continue another time.
In the meanwhile, though, here is a reminder of what I'm aiming for:
Followup The themes in this post are continued here