Link together gcc and mikroC projects for STM32
This code was originally developed because I had to quickly deploy a project which I was not able to build using mikroC PRO for ARM. However, other parts of the project used hardware libraries provided by mikroC. I did not have the time to rewrite those libraries, and thus could not deploy the project using only gcc. Therefore, the solution was to create a kind of a linker to put together both projects.
The example is meant for a STM32F407VG microcontroller, for example the one present in the mikromedia for STM32 board.
- Install a bare metal ARM toolchain. Build your own or download a prebuilt toolchain.
- Install libopencm3.
- Clone this repository.
- Go to the
example/example-gcc
directory, and create a symbolic link to the libopencm3 directory. For example:cd mikrostm-link/example/example-gcc && ln -s /home/user/codes/libopencm3 .
- Go back to the
example
directory, and runmake
. - Program your board with the generated
example.hex
file using mikroe-uhb or another programmer.
Other STM32 devices should be straightforward to support. Just modify FLASH_SIZE
and RAM_SIZE
in the first lines of the mikrostm-link
file. Also, remember to modify Makefile.include
and the ld script of the gcc project accordingly.
Other microcontrollers should be doable to support, but I did not care much about code extensibility. This was just a quick hack!
This is a quick guide on how to create a pair of projects which can be linked together. Please use the example for further reference.
- Declare the functions which you want to import from the gcc project as function pointers. For example:
void (*const reset_handler)(void) = 0xdeadbeef;
void (*const my_function)(void) = 0xdeadbeef;
The functions can point to any address. The addresses will be modified later by mikrostm-link directly in the generated .hex file.
-
The
reset_handler
function is always needed. It is already implemented for you, and its purpose is to call any required initialization code. You need to call this function from you mikroC project before calling any other function imported from the gcc project. -
You need to force the mikroC linker to include in its output the functions which you want to export to gcc. If the functions are not used in other parts of your mikroC project code, you can easily do this by inserting a dead code section inside your
main
function:
if(0) {
// functions imported by gcc
asm {
BL _HID_Read;
BL _HID_Write;
};
}
- Please build your mikroC project before calling mikrostm-link. This is needed because mikrostm-link was originally designed to be used in a Linux system, with mikroC running inside a Windows VM.
-
Use our
Makefile
as a template. Modify it to build objects for each source file of you project. Keep thereset_handler.c
file intact and always list itsreset_handler.o
object in theMakefile
. -
Create an
imports.h
file containing a constant pointer to each function and to each variable which you want to import from the mikroC project. For example:
static char (*const HID_Read)(void);
static unsigned char *const readbuff;
This file will be modified by mikrostm-linker each time it runs, in order to initialize the pointers with their correct addresses.
- Create an
exports.ld
file containing anEXTERN
declaration for each function you want to export to the mikroC project. For example:
EXTERN (do_calculation)
When you run mikrostm-link, it:
- Reads symbol positions from the
*.lst
file generated by the mikroC compiler. - Creates a
memory_map.ld
file which instructs ld to link the gcc project only after the memory already being used by the mikroC project. - Modifies the
imports.h
file, inserting the correct addresses. - Runs
make
in the gcc project directory. - Glues together the
.hex
files generated by mikroC and by gcc, and replaces pointers to functions imported by mikroC with the correct addresses.
- Linaro GCC 4.8-2013.07-1
- mikroC PRO for ARM version 3.3.1.0
- mikroC PRO for ARM version 4.0.0.0