# Can I use just plain GCC to compile program for Nucleo?

I have a ST Nucleo F446RE. It's an ARM board which provides quite an interesting interface for uploading programs - it presents itself as USB storage device and the program can be copied on it, which causes Nucleo to reset and launch the program.

As such, I'm kinda reluctant to even bother installing (yet another) development toolchain. I'd rather just use GCC compiler, some makefile for compiling and flashing and probably some required Nucleo header libraries.

Is there a way to setup lightweight environment like this for Nucleo? It's probably worth mentioning that I'm a newbie to emdedded development.

• yes, arm-none-eabi-gcc, but should be moved to stackoverflow. – user3528438 Feb 8 '17 at 13:19
• @user3528438 Afaik, embedded and microcontroller questions fit much better here. – Tomáš Zato Feb 8 '17 at 13:21
• Do you use Eclipse for other development, by chance? – bitsmack Feb 10 '17 at 1:39
• @bitsmack We considered eclipse. But we wanted to have a basic toolchain that is lightweight and will work for everyone. Individuals can then install eclipse or whatever they like, but will still have fallback option if it doesn't work. – Tomáš Zato Feb 10 '17 at 9:32
• @m.Alin mentioning the ability to download a GCC-compatible version of one's project from the mbed site could rescue your deleted answer. – Chris Stratton Feb 10 '17 at 18:37

As for any other processor, you will need a compiler that targets the CPU you're using.

In other words, yes, you should/can use the GCC, but: you can't use the gcc that targets your PC, but need to use a GCC that targets the processor.

In this case, the compiler would be called arm-none-eabi-gcc (for ARM ISA, with no OS, with the extended application binary interface), and you'd need to tell the linker (which must also target the same platform) how much memory you have in which address spaces (that's the job of a linker script). Then you'd probably also want an arm-none-eabi-gdb; in essence, you need a complete arm-none-eabi toolchain.

But this toolchain is pretty easy to get; on my systems (Fedora Linux), that'd be as complicated as using dnf search arm-none-eabi to find the packages I want and then dnf installing those.

Often, you can use your existing editor/IDE environment pretty smoothly for embedded development simply by telling it that it has to prefix each executable name (gcc, as, ld, …) with arm-none-eabi; done.

• I found some downloads for Ubuntu and Windows, that looks promising! – Tomáš Zato Feb 8 '17 at 13:48
• @TomášZato don't just download anything. If Ubuntu ships a arm-none-eabi toolchain, use that. As staringlizard said, use the linker script from ST's stm32cubef4 toolig. – Marcus Müller Feb 8 '17 at 14:19
• @TomášZato As Marcus says, on Ubuntu, install te compiler like this: sudo apt-get install gcc-arm-none-eabi – m.Alin Feb 8 '17 at 14:27
• Ok, I have spent good few hours meddling with this. Empty main() compiles IFF you use --specs=nosys.specs parameter. That produces a.out which does not run when I copy it on Nucleo's virtual drive. This answer was a very good lead, but I think it's missing the part regarding even basic hint on how to use the arm-none-eabi toolchain. I tried it on windows and linux with the same result. – Tomáš Zato Feb 8 '17 at 15:53
• @TomášZato well, this is an embedded device. Putting something on a drive that the firmware bootloader offers you will not make the device suddenly do what you want. I recommend starting with the tutorials and examples that come with stm32cubef4 toolset. And really, maybe an IDE where everything is already set up for you might not be that bad a choice if you're as inexperienced with ARM development as your comment might indicate. – Marcus Müller Feb 8 '17 at 16:17

As other answers state, you want to use arm-none-eabi-gcc to compile your code.

However, compiled code (by itself) doesn't do much good! You need to convert it to an .elf or .hex format. You need to be able to load it to the microcontroller. You probably want to be able to debug the code on the target.

I recommend using the free GNU ARM Embedded Toolchain. It is only the toolchain; it doesn't provide an IDE. It's a single install, and includes:

• arm-none-eabi-gcc (to compile code)
• arm-none-eabi-gdb (to debug)
• arm-none-eabi-objcopy (to translate to .hex)
• arm-none-eabi-size (to get a readout on your code's memory utilization)
• (more)

It's maintained by ARM developers and is available for Windows/MacOS/Linux.

There is a separate project for ARM development using Eclipse IDE, called GNU ARM Eclipse. Even if you don't want to use Eclipse, I recommend scanning their website. They explain how to install the GNU ARM Embedded Toolchain, how to set up different debuggers, etc.

By the way, GNU ARM Eclipse is particularly good for ST ARM development. It has built-in linker scripts for the different ST families, has ties to ST's Standard Peripheral Libraries, etc.

Finally, I realize that this bypasses the custom USB programming interface presented by the Nucleo. My personal opinion is that you should use these standard tools instead, mostly because you will end up using them when you want to port your code to a non-Nucleo board.

Responding to your comment, I've never seen a.out ("assembler output") used for ARM microcontrollers. In my projects, I generally have many c files, each which compile to an object file. Then the objects are combined with the linker, which outputs a hex or elf file.

Here's some extra info in case it helps:

My compile commands are complicated, but they are handled by my IDE so it's transparent to me. Here is an example for main.c:

arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -Og -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -Wunused -Wuninitialized -Wall -Wextra -Wmissing-declarations -Wpointer-arith -Wshadow -Wlogical-op -Waggregate-return -Wfloat-equal -g3 -DUSE_FULL_ASSERT -DDEBUG -DTRACE -DSTM32F10X_CL -DUSE_STDPERIPH_DRIVER -DHSE_VALUE=12000000 -UOS_USE_SEMIHOSTING -UOS_USE_TRACE_SEMIHOSTING_STDOUT -I"../include" -I"../include/usb" -I"../system/include" -I"../system/include/cmsis" -I"../system/include/stm32f1-stdperiph" -I"../system/STM32_USB_Device_Library/Core/inc" -I"../system/STM32_USB_Device_Library/Class/cdc/inc" -I"../system/STM32_USB_OTG_Driver/inc" -std=gnu11 -Wmissing-prototypes -Wstrict-prototypes -Wbad-function-cast -MMD -MP -MF"src/main.d" -MT"src/main.o" -c -o "src/main.o" "../src/main.c"

This includes hook into the Standard Peripheral Libraries ("SPL"), options to allow debugging, etc. If you stripped out all the includes, warnings, and SPL stuff (but you shouldn't actually strip out the warnings!), you are still left with:

arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -Og -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -g3 -std=gnu11 -MMD -MP -MF"src/main.d" -MT"src/main.o" -c -o "src/main.o" "../src/main.c"

Some of these may still be unnecessary, but it gives you an idea of what is required.

Then, after all the object files are created, they are linked like so: (I've simplified the following command)

Invoking: Cross ARM C++ Linker

arm-none-eabi-g++ -mcpu=cortex-m3 -mthumb -Og -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -g3 -T mem.ld -T libs.ld -T sections.ld -nostartfiles -Xlinker --gc-sections -L"../ldscripts" -Wl,-Map,"MotioSens_AP.map" --specs=nano.specs -o "MotioSens_AP.elf" ./src/main.o ./{my other object files}.o

Finished building target: MotioSens_AP.elf

Some of the command options are duplicated, and so might me unnecessary to pass into both the compiler and the linker. Again, since my IDE handles it, I haven't really paid attention :)

These complexities in ARM development are one of the reasons that I started using an IDE (Eclipse, in my case).

• I installed the toolchain, that's how I produced the binaries. But I just fail to understand how are they used to generate the hex files. If I could do that, I'd be all set. All that is left is to copy that binary on Nucleo's virtual drive. – Tomáš Zato Feb 10 '17 at 17:29
• @TomášZato Hi, I added info to my answer. I hope it is helpful! – bitsmack Feb 10 '17 at 17:52
• It is, too bad I can't upvote a second time! – Tomáš Zato Feb 10 '17 at 20:21

Yes, you can!

You can get your linker script from the stm32cubef4. Then just make a simple Makefile and you are ready to rock. Make sure that you link in the basic stuff (CMSIS). The cubef4 contains plenty of examples that you can look at if unsure.

Of course you will need the gnu tool chain. Just search for arm-none-eabi-gcc and you will find it.

• Way oversimplified answer.. – m.Alin Feb 8 '17 at 13:50
• @m.Alin I know you are shocked, but it really is as simple as this. World is better without an over complex IDE environment. – staringlizard Feb 8 '17 at 13:56
• What is "stm32cubef4"? Example code? Or STM32cubeMX (the program)? – Peter Mortensen Feb 13 '17 at 19:25
• @PeterMortensen STM32CubeF4 is a zip package containing code examples for almost all of the peripherals and development boards of the F4 series. – Bence Kaulics Feb 13 '17 at 19:53

Is there a way to setup lightweight environment like this for Nucleo?

Technically speaking, the (right) compiler is all you need. ARM maintains a GCC variant for their chip and you can download it and that's all there is.

But, in reality, you may want to investigate two things:

1. An IDE: It makes life easier for most by incorporating editing, building and debugging all in one. There are tons of them, both free, near-free and commercial. More under Windows than not.

2. Libraries: It makes quick development of your code easier. There are third-party ones for graphics, LCD, ..., and there are vendor ones, from ST for example. You can develop code for your chip without the use of such libraries, to be clear.

Which ones you may find useful is entirely subjective. Personally, I code off of a set of IDEs and I sometimes use OEM libraries. But it can be subjective.