ARM Toolchain

http://openhardware.net/Embedded_ARM/Toolchain/

This toolchain is built from the more recent gcc-4.3.2 source.

The toolchain will be suitable to use for ARM7TDMI ARM32 or Thumb code. This is the toolchain I use to build the RDCF2 filesystem, NewLib stubs and the application code for the LPC2000 processsors. The following directions will give you an ARM7TDMI Thumb toolchain + NewLib ready to use to develop applications.

Topdisclaimer

While the toolchain will also produce ARM32 code, the arm-elf-gcc will have to have interworking switch on (-mthumb-interwork) enabled if you use the newlib. The newlib build creates a Thumb version of the library, not a pure ARM32 library.


TopPrepare to build your toolchain: collect the sources

The packages that are being used are: gcc-4.3.2, binutils-2.19, Insight-6.8, and NewLib-1.16.0. I like to build my development environment from source as I find that I not only have more control over the build process, but then I don’t have to worry about keeping track of where I downloaded a prebuilt package. Or that the webpage for the package has disappeared. I only have to keep the scripts around to rebuild later on.

These are the source files that you will need:

  • binutils-2.19.tar.bz2
  • gcc-4.3.2.tar.bz2
  • newlib-1.16.0.tar.gz
  • gcc-4.3.2_patch.gz
  • newlib_makefile_patch.gz

    You will also need some scripts to build the toolchain:

  • 00setSources.sh
  • 01makeBinUtils.sh
  • 02makeBootGcc.sh
  • 03makeNewLib.sh
  • 04makeRealGcc.sh
  • 05makeInsight.sh
  • allclean.sh
  • environ.sh

    NOTE: Insight 6.8 will no longer build properly on the newest xorg systems due to some problem with tk. The CVS version will build and appears to work fine.

  • TopGetting ready to build

    Note: All operations are done as an unpriviliged user, you do not have to be root to build this toolchain, to install, or use it.
    Note: Scripts will install the results under $HOME/DevelToolbin/binaries/armThumb-4.3.2/ .

    If this is not where you want the binaries, then edit the environ.sh script and change the PREFIX.


    TopCreate and populate the build tree

    Next is to make a directory tree to hold the sources and perform the builds: mkdir -p $HOME/ArmTools/downloads. Put the build scripts and other files you downloaded into the locations shown. Your tree will now look like this:
    ArmTools/
     |– 00setSources.sh
     |– 01makeBinUtils.sh
     |– 02makeBootGcc.sh
     |– 03makeNewLib.sh
     |– 04makeRealGcc.sh
     |– 05makeInsight.sh
     |– allclean.sh
     |– downloads
     |   |– binutils-2.19.tar.bz2
     |   |– gcc-4.3.2.tar.bz2
     |   |– gcc-4.3.2_patch.gz
     |   |– insight-6.8.tar.bz2
     |   |– newlib-1.16.0.tar.gz
     |   `– newlib_makefile_patch.gz
     `– environ.sh


    TopBuild the tools!

    Make the scripts executable: chmod u+x ArmTools/*.sh. We will now run all scripts in numerical succession, invoke them one-by-one to build each package. The first script sets the unpacks the sources into locations where the other scripts will build from.

    From a user login (not as root), invoke the first script as ./00setSources.sh, and remaining scripts are also run as : ./ (e.g. ./00setSources.sh, ./01makeBinUtils.sh, ./02makeBootGcc.sh, etc.). All scripts should complete without errors, when done, the $HOME directory will have a subdir called “devtools/armThumb/”.

    Note, if you wish to place the resulting binaries in a location other than what I have chosen, edit the environ.sh script and change the PREFIX location.

    WARNING!: From reports from Ubuntu users, it appears that Ubuntu turns on, by default, some rather stringent gcc options that will cause any code, that is not absolutely perfect, to fail to build. I’ve added the ‘–disable-werror’ option to the configures to attempt to avoid this. Let me know if something else is needed for a successful build on Ubuntu?


    TopGetting ready to use the new tools

    We are almost ready, but first you need to set a path to the new gcc cross compiler, binutils and insight. YMMV, each system is slightly different, on Mandrake I now edit $HOME/.bash_profile and add the new PATHs. My path statement in the .bash_profile is: PATH=$PATH:$HOME/bin:$HOME/devtools/armThumb/bin


    TopFinishing up

    Okay, you are done! Create an icon on your desktop to point to the Insight binary at $HOME/devtools/armThumb/bin/arm-elf-insight to have that handy. Next is to go out on the web and get a project framework (project sources) to begin building your project!

    A note about the NewLib source and build tree, leave them under $HOME/devtools/armThumb/ (newlib_sources, newlib_build). By leaving those directories, you can do source level debugging of NewLib should it become necessary. However, if you don’t want the various NewLib functions appearing in Insights’ function list, you can safely delete those subdirs.


    TopAnnoying Insight problem

    One thing that drove me crazy about Insight is that it didn’t seem to want to save my sessions. A session is created whenever you configure the target settings, open an elf file, and connect to the target. But, Insight seemed to follow some unknown method of determining just when it would save that information

    Finally, I discovered that there are two ‘.gdbtkinit’ files (the session information). One of these are located in the user home ($HOME) directory, this is the one that insight reads from when it starts. There is a second session file that is created / updated each time you exit from an Insight session. That second session file is in the project subdirectory, the place that you did the ‘File | Open’ into.

    The session file in the user home directory is only written when it does not yet exist. The session file within the project appears to never be read from, it is only written to on each exit from Insight. So, run Insight, go through the motions of a session: ‘File | Target settings’, ‘File | Open’, ‘Run | Connect’, ‘Run | Disconnect’, and finally ‘File | Exit’. Copy the .gdbtkinit from the project subdirectory to your home directory, overwrite any file currently there. Now, when you next run Insight, you will have the “correct” session!


    TopMultiple Insight Project Selections

    According to the Insight docs, you can have up to five project selections in the ‘File’ menu. You would think that Insight would behave like every other program that keeps a list of recent files, or history, and do this automagically? Nope, it doesn’t. Sounds stupid, but Insight is brain-dead when it comes to keeping a simple list of “the last 5 projects”. :-/

    Yes, you can have a list of recent projects, however you have to do this by manually editing .gdbtkinit files yourself. You have to modify the [gdb] and [session] sections of .gdbtkinit. This is a bit tricky to do, but if you follow these steps, you can easily get it done.


  • remove the ~/.gdktkinit and those within the project directories. We need to start fresh here with nothing known about any sessions.
  • run insight. Do nothing but setup your preferences. I open a breakpoint, console and register window, resize and locate them. Then I set the target settings under ‘File | Target’ and exit Insight (‘File | Exit’).
  • Make an archival copy of the ~/.gdbtkinit as another name to save this starting point for reference (cp ~/.gdbtkinit gdbtkinit.start).
  • Make a working copy ~/.gdbtkinit as we will be using it to add the other sessions to this copy (cp ~/.gdbtkinit gdbtkinit.all).
  • 1. Run Insight again, the windows should now appear as you had laid them out.
  • 2. Open your first elf file, just do a ‘File | Open’, your target settings need to be set again (‘File | Target settings’). Go through all the motions of a session, connect to the target, etc.. Now, disconnect from the target (‘Run | Disconnect) and exit Insight (‘File | Exit’). This will now create a .gdbtkinit in that project directory.
  • 3. Copy gdbtkinit.start over the ~/.gdbtkinit in the user home directory. This will revert us back to the original setup of just having a basic session configured.
  • Repeat steps 1-3 as many times as needed to create .gdbtkinit sessions into each of your project directories.
  • Now, verify each of these project session are complete by copying them over the ~/.gdbtkinit and running Insight. You only want one project to show up in the list of recent projects. Test the session, everything should connect / download as it should to the target.

    That certainly was a bit of work, but we are almost there. Now we will combine the necessary session data into a single file. Starting with the copy we named gdbinsight.all, edit that file and all the project sessions.

  • Copy the section [session] from each of the projects into that of gdbinsight.all.
  • From each project, copy into section [gdb] the line that says ‘recent-projects=’. Once each line is copied, concatenate them into a single, space separated list. e.g. ‘recent-projects = …’
  • Save the new gdbtkinit.all and copy it over ~/.gdbtkinit. When you run Insight now, it will have your all your project sessions in there.

    One thing I never do is to trust Insight not to mess up its .gdbtkinit file. 😦 Hard experience has taught me to keep a multiple project session file backed up somewhere, ready to copy over a boinked ~/.gdbtkinit file.


  • TopWhat not to use!

    I strongly urge anyone not to use any gcc version 3.x to build Thumb code!

    There is an optimizer bug (-Os) prior to version 4 which sometimes shows up as a stack corruption during interrupts. The bug is not easy to force to appear, it seems to take a number of conditions within a function source to be present. If an interrupt occurs while executing that function, the contents of the stack will most likely be corrupted. One of the conditions which could create the bad code appears to be related to instantiating a local variable inside a code block and the size of the local is determined by a math calculation. Something like this:

    void function_bad (void) {
    struct ELEMENTS foobar;  // struct defined locally.

     for (i=0;i<MAX;i++) {  // do some test to get a variable count.
       if (some_test) foobar.elements++;
     }
     …
     { // locally declare a variable length array of struct FOO.
       struct FOO foo [4 * foobar.elements];
       …  // now we are probably in danger for stack corruption via interrupts,
       …  // if the interrupt occurs while excuting this code!
     }
     …  // interrupt may not affect us here.
    }

    The problem is that gcc copies the value of the SP reg into R7, then allocates stack space for the variables within the embedded block (e.g. struct FOO foo) by decrementing R7. When an interrupt occurs, data is written onto the stack (SP) due to the interrupt and any stack space the interrupt uses will overwrite the variables that R7 has created.

    I have been given code that does create this situation, it is not a myth! So, do not use gcc-3.x to generate ARM Thumb code! Now, this occurs when gcc-3.4.x emits Thumb code, under those conditions, even though there does not appear to be evidence that this does occur when building ARM32 code, I think this is reason enough not to use gcc-3.x! The gcc versions prior to 3.4 had other issues when generating ARM32 code…

    Leave a comment