Getting Started with WinARM for Qualcomm BREW
Getting started in Qualcomm BREW development has its share of hurdles, but two in particular seem to discourage the small-scale (startup or academic) developers. The first is becoming an Authenticated BREW developer, the process of signing up for a Verisign certificate and signing Qualcomm's developer agreement, required before you can have access to the Qualcomm BREW Extranet with its tools such as the BREW Signature File Generator and the BREW AppLoader. The second is obtaining a quality tool chain for the target hardware: Whereas the tools from ARM are first-rate, they're also prohibitively expensive. (The lowest-cost option for the ARM tool chain costs more than the laptop I regularly use to run it!) Although GCC for ARM based on GCC 3.x is both supported by Qualcomm and widely available, its output is often larger, and it lacks support for Thumb, the small-footprint extension to the ARM architecture makes it difficult to create truly small binaries. Fortunately, with the advent of WinARM supporting both ARM7 and Thumb output, there's a GCC-based solution for building binaries for BREW-enabled handsets. Although it won't help you navigate Qualcomm's legal agreement and get you access to the Qualcomm BREW Extranet, once you're there it's an excellent way to begin building your applications for evaluation on handsets.
Instructions to use WinARM for BREW aren't hard to find—Ward Willats published a great HOWTO at http://brew.wardco.com/index.html back in May of 2006. It does, however, require some patience and tweaking of your makefile (even if you've previously used GCC) to get it right, so in the spirit of Qualcomm when supporting GCC 3.x, this article includes a custom make file that uses WinARM to build Qualcomm's WhiteBoard developer sample. You can either use the instructions in this article and at Ward's Web site to create your own make file, or begin with the WhiteBoard.mak available here.
To begin, you need a copy of WinARM. I downloaded mine, version 4.1.1, from http://gandalf.arubi.uni-kl.de/avr_projects/arm_projects/#winarm; the ZIP files at this link are pre-built and can be decompressed right to the directory where you want to install the tools. (I installed mine at the root of my boot drive, in c:WinARM). The advantage of using this release—besides that it's precompiled and ready to go—is that it has no dependencies on cygwin. To install WinARM:
- Download the archive.
- Unpack the archive to a known location such as c:WinARM.
- Set the environment variables GCCHOME and GCCLIBPATH. GCCHOME should be set to the directory where you unpacked WinARM (for me, c:WinARM); GCCLIBPATH must be set to the lib directory inside your WinARM directory (for me, c:WinARMlib).
- Add c:WinARMbin to your PATH environment variable.
- Re-start any command line windows or command shells (say, in a text editor such as Emacs you may be using) to pick up the environment variable changes.
You also need Qualcomm's support files for GCC, which requires you to have Qualcomm BREW Extranet access so you can download the files from the Qualcomm's site. The archive contains two key things: a BREWelf2mod that can convert the ELF file from the linker to a mod file, and the GCCResolver.c file that contains definitions of memcpy and memset functions used by the GCC tool chain when creating the start-up code for your application. You will want to put GCCResolver.c someplace where you can get at it when you're building your project, and of course the BREWelf2mod tool must be placed somewhere in your path. If you're working with a team of developers, it's best to powwow about where to put these so that everyone's putting them in the same place, because they're not linked to a specific BREW SDK version. I include the GCCResolver.c in my project just like any of my other source files, and by convention, I've put the BREWelf2mod command in my c:WinARMbin directory so I don't have yet another directory with a single binary in my path.
Creating the Make File
Although I'm an old UNIX fan, I'm presently working in a shop that predominantly uses Microsoft Windows. Consequently, it's nmake for me all the way—this keeps me from inflicting cygwin on my coworkers, and more closely matches the development environment directly supported by Qualcomm anyway. Because writing an make file for nmake from scratch is beyond the scope of this article, I offer the time-tested suggestion of finding one that works for someone else in another project and making it work to suit your needs. In my case, I began with an autogenerated make file for nmake and gcc 3.x using the Microsoft Visual Studio Plug-In for BREW available at https://brewx.qualcomm.com/bws/content/gi/products/vsaddins/3.0/188.8.131.52/web_install/install.htm. The make files generated by this tool are sufficient for small projects for single developers, but if you're building a large project or cooperating with many developers who may have slightly different configurations, you'll find quickly that you need to invest additional time in making a more capable make file for the handset.
Once you've created a basic make file, you must edit it as follows:
- Make sure the paths to the various build tools (the compiler and linker) are correct.
- Make sure the paths to the various build inputs (BREW SDK include files, BREW SDK source files, your source files, and so forth) are correct.
- Make sure the path to BREWelf2mod is correct.
- Make sure your target objects and input sources are correctly specified.
Step 2 is especially important—be sure you're building the correct version of the SDK for your target handset. Class IDs for innocuous interfaces such as IFileMgr have been known to change in later versions of BREW; running with a binary built with a newer version of the SDK than the handset supports can cause crashes that look suspiciously similar to crashes caused by incorrect compiler options; often, your application just fails to launch and resets the handset.
Exactly how you do this depends on the make file you choose; if you're lucky, the make file you start with is well-commented and this shouldn't take very long. You can debug your make file at this point using the /N option to nmake, which executes your make file but does not execute the actual commands to build your application, letting you see what commands nmake thinks it needs to build your executable. Qualcomm's make files are reasonably commented; be sure to check the values of the following environment variables: BREW_HOME, BREW_ADDINS, GCC_HOME, and GCC_LIBPATH.
Setting Compiler Options
When compiling C files for BREW using WinARM, you must specify the following options:
winarmbinarm-elf-gcc.exe -mlittle-endian -mcpu=arm7tdmi -mapcs-frame -fno-builtin -ffunction-sections -fshort-enums -D_DEBUG -DDYNAMIC_APP -I ... -o file.o -c file.c
The first argument specifies little-endian byte order, the default for most handsets (check your handset's data sheet to be sure). The second specifies the ARM7 processor, and the third the standard mechanism for C stack frames. The fourth and fifth arguments specify that library functions should not be inlined (especially important, as you should be using BREW helper functions anyway) and that each function should be put in its own code segment, so that the linker can dead-strip unused functions. The last switch, -fshort-enums, tells the compiler to fit enumerations into the smallest number of bytes, and is good for saving some space in structures. Finally, if you're compiling a debug build, be sure to include .D_DEBUG, and all applications should include .DDYNAMIC_APP. Of course, use the .I switch to specify your include paths, and the .o switch to declare the output file for the compilation.
Where you set these depends on the make file you're using; in make files provided by Qualcomm, look at the CODE and INC variables.
Page 1 of 2