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.

  • 2
    \$\begingroup\$ yes, arm-none-eabi-gcc, but should be moved to stackoverflow. \$\endgroup\$ Commented Feb 8, 2017 at 13:19
  • 4
    \$\begingroup\$ @user3528438 Afaik, embedded and microcontroller questions fit much better here. \$\endgroup\$ Commented Feb 8, 2017 at 13:21
  • \$\begingroup\$ Do you use Eclipse for other development, by chance? \$\endgroup\$
    – bitsmack
    Commented Feb 10, 2017 at 1:39
  • 1
    \$\begingroup\$ @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. \$\endgroup\$ Commented Feb 10, 2017 at 9:32
  • \$\begingroup\$ @m.Alin mentioning the ability to download a GCC-compatible version of one's project from the mbed site could rescue your deleted answer. \$\endgroup\$ Commented Feb 10, 2017 at 18:37

5 Answers 5


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.

  • \$\begingroup\$ I found some downloads for Ubuntu and Windows, that looks promising! \$\endgroup\$ Commented Feb 8, 2017 at 13:48
  • \$\begingroup\$ @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. \$\endgroup\$ Commented Feb 8, 2017 at 14:19
  • 2
    \$\begingroup\$ @TomášZato As Marcus says, on Ubuntu, install te compiler like this: sudo apt-get install gcc-arm-none-eabi \$\endgroup\$
    – m.Alin
    Commented Feb 8, 2017 at 14:27
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Feb 8, 2017 at 15:53
  • \$\begingroup\$ @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. \$\endgroup\$ Commented Feb 8, 2017 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,"AP.map" --specs=nano.specs -o "AP.elf" ./src/main.o ./{my other object files}.o

Finished building target: 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).

  • \$\begingroup\$ 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. \$\endgroup\$ Commented Feb 10, 2017 at 17:29
  • 1
    \$\begingroup\$ @TomášZato Hi, I added info to my answer. I hope it is helpful! \$\endgroup\$
    – bitsmack
    Commented Feb 10, 2017 at 17:52
  • \$\begingroup\$ It is, too bad I can't upvote a second time! \$\endgroup\$ Commented Feb 10, 2017 at 20:21
  • \$\begingroup\$ Where do you find the mem.ld, libs.ld, and sections.ld files? \$\endgroup\$
    – oxr463
    Commented Jul 1, 2019 at 0:45
  • 1
    \$\begingroup\$ @LucasRamage They are part of the GNU ARM Eclipse template I mentioned. As an alternative, ST provides a single linker file for each of their microcontrollers. You can find these in STM32Cube, or (probably) directly from ST's website. \$\endgroup\$
    – bitsmack
    Commented Jul 6, 2019 at 0:27

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.

  • 2
    \$\begingroup\$ Way oversimplified answer.. \$\endgroup\$
    – m.Alin
    Commented Feb 8, 2017 at 13:50
  • 1
    \$\begingroup\$ @m.Alin I know you are shocked, but it really is as simple as this. World is better without an over complex IDE environment. \$\endgroup\$
    – MathiasE
    Commented Feb 8, 2017 at 13:56
  • \$\begingroup\$ What is "stm32cubef4"? Example code? Or STM32cubeMX (the program)? \$\endgroup\$ Commented Feb 13, 2017 at 19:25
  • \$\begingroup\$ @PeterMortensen STM32CubeF4 is a zip package containing code examples for almost all of the peripherals and development boards of the F4 series. \$\endgroup\$ Commented Feb 13, 2017 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.


In short, you need a cross compiler. a gcc c/c++ compiler you may have is going to build for your specific platform (linux or windows), and it will target x86_64 processor which has a different instruction set.

https://wiki.osdev.org/Why_do_I_need_a_Cross_Compiler This wiki explains, why and how to build a cross compiler, it takes less effort then making your self a cup of tea. It is a very good idea to build your own set of tools for educational value. Once you have your toolchain, you can add any libc or libcc you wish, and you will know your way around toolchain.

Even shorter, there is a toolchain that is already prebuilt and includes libc and libcc developed by arm. Which you can find at the end of the wiki i linked or https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.