MinGW is a Windows port of the open source GCC compiler. It will compile native Windows executables from C, C++, and a few other languages. In this post we document our experience compiling the pirate-loader bootloader application.
Pirate-loader, originally written for Microsoft Visual C, is a C program that uploads a new firmware to the Bus Pirate. We’re going to recycle the code in a cross-platform PIC programmer. Pirate-loader has everything we need to get started: serial port read/write routines, a HEX file parser, and a command line options handler to interpret user settings.
Step 1. Download and install MinGW
First download and install the MinGW compiler. When we wrote this, MinGW was in the process of creating a new installer application. If you want the latest version you can follow these directions, we just used the older automatic installer instead. The installer we used was a small executable that downloaded and installed the necessary files after detecting the system type.
For convenience, it’s best to add the compiler location to your path so it will run from any directory. Right click on My Computer, choose properties->advanced->environment variables->system variables, and add the path to MinGW (c:\mingw\bin on our system).
Step 2. Download pirate-loader.c source
The pirate-loader source is in the Bus Pirate SVN. It’s a single file, so it’s easy for a beginner to download and deal with (direct download link). We saved this file in c:\mingw, but you can compile it from anywhere if you setup the MinGW path in step 1.
Step 3. Attempt to compile
Now we can attempt to compile. This is a really simple program, so we can compile it directly without a make file.
gcc pirate-loader.c -o pirate-loader.exe
The command syntax is shown above. The first argument specifies the source code files needed to compile the program. -o sets the name of the compiled output file that will be created.
The first compile isn’t successful. The output reports that write, read, and open are already defined in \include\io.h.
Step 4. Fix it for MinGW
We need to address the compiler error before we can go any further. First, we opened pirate-loader.c with a text editor. Notepad++ is our favorite because it recognizes and highlights most programming languages, and it has good search and replace functions.
We searched for the offending functions (write, read, and open) and found them near the top of the source. They’re surrounded by an #ifdef WIN32 compiler directive, which means that these functions are only included when compiled for Windows.
Next we loaded the \include\io.h file and looked for the same functions. They’re also defined in io.h, the duplicate function names are causing the error. Our guess is that these are Linux specific functions not supported by Windows, so Piotr, the pirate-loader author, wrote some compatible replacements. WinGW, being a Linux-origin compiler, probably includes these already for convenience.
#ifndef _UWIN _CRTIMP int __cdecl __MINGW_NOTHROW access (const char*, int); _CRTIMP int __cdecl __MINGW_NOTHROW chsize (int, long ); _CRTIMP int __cdecl __MINGW_NOTHROW close (int); _CRTIMP int __cdecl __MINGW_NOTHROW creat (const char*, int); _CRTIMP int __cdecl __MINGW_NOTHROW dup (int); _CRTIMP int __cdecl __MINGW_NOTHROW dup2 (int, int); _CRTIMP int __cdecl __MINGW_NOTHROW eof (int); _CRTIMP long __cdecl __MINGW_NOTHROW filelength (int); _CRTIMP int __cdecl __MINGW_NOTHROW isatty (int); _CRTIMP long __cdecl __MINGW_NOTHROW lseek (int, long, int); //_CRTIMP int __cdecl __MINGW_NOTHROW open (const char*, int, ...); //_CRTIMP int __cdecl __MINGW_NOTHROW read (int, void*, unsigned int); _CRTIMP int __cdecl __MINGW_NOTHROW setmode (int, int); _CRTIMP int __cdecl __MINGW_NOTHROW sopen (const char*, int, int, ...); _CRTIMP long __cdecl __MINGW_NOTHROW tell (int); _CRTIMP int __cdecl __MINGW_NOTHROW umask (int); _CRTIMP int __cdecl __MINGW_NOTHROW unlink (const char*); //_CRTIMP int __cdecl __MINGW_NOTHROW write (int, const void*, unsigned int); #endif /* _UWIN */
The easiest fix is to comment these functions out of the io.h code with ‘//’. We also tried removing the functions from pirate-loader.c and relying on the version in io.h, but they are not directly compatible. We’re not sure of the ‘best practice’ fix, and welcome suggestion in the comments.
Step 5. Compile again
Now we can compile again. The compiler didn’t report any errors and created pirate-loader.exe.
pirate-loader --dev=COM3 --hello
Finally, we connected a Bus Pirate with the bootloader enabled and tested the freshly compiled pirate-loader executable. The connection syntax is shown above, remember to substitute the correct COM port number for your system. The compiled application successfully connected to the Bus Pirate and read the firmware version.
Now we’ve got an application that compiles in MinGW with all the building blocks we need for a cross-platform PIC programmer. We’re discussing this project further in the forum, your input is welcome.