3

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.

bitsmack
  • 16,747
  • 9
  • 52
  • 108
Tomáš Zato
  • 1,044
  • 4
  • 21
  • 40
  • 2
    yes, arm-none-eabi-gcc, but should be moved to stackoverflow. – user3528438 Feb 08 '17 at 13:19
  • 4
    @user3528438 Afaik, embedded and microcontroller questions fit much better here. – Tomáš Zato Feb 08 '17 at 13:21
  • Do you use Eclipse for other development, by chance? – bitsmack Feb 10 '17 at 01:39
  • 1
    @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 09: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

5 Answers5

8

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.

Marcus Müller
  • 88,280
  • 5
  • 131
  • 237
  • I found some downloads for Ubuntu and Windows, that looks promising! – Tomáš Zato Feb 08 '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 08 '17 at 14:19
  • 2
    @TomášZato As Marcus says, on Ubuntu, install te compiler like this: `sudo apt-get install gcc-arm-none-eabi` – m.Alin Feb 08 '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 08 '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 08 '17 at 16:17
  • @MarcusMüller I'm sure I remember that mbed.org produced a binary that you could copy and it did do what you wanted. That's all I need, just without clumsy remote website. Is it really that complicated? – Tomáš Zato Feb 08 '17 at 16:46
  • @TomášZato Yes, it is really that complicated! That's why I recommended the mbed platform. You need to pass the right compiler flags to the cross-compiler, you need to add a linker file, you need to possible add startup code and so on. But if you really don't want to use the online compiler, the best next thing is to install an IDE. It will make your life a lot more easier than doing it without any IDE, despite what `staringlizard` is saying. – m.Alin Feb 08 '17 at 17:52
  • @TomášZato - you can usually export your mbed projects as a zip with a GCC-compatible linker script and Makefile that already handles all of the issues being mentioned. There are various issues, and various complaints about mbed but it is a workable flow that might meet your simplicity goals, and if you put some time into retrofitting sense into the autogenerated Makefile, could be a starting point for your own system. Though save yourself some frustration by doing a recursive "touch" to normalize file dates before building. – Chris Stratton Feb 10 '17 at 18:35
  • you can apt-get one on ubuntu or go to https://developer.arm.com/open-source/gnu-toolchain/gnu-rm and get a pre-built gnu toolchain or just build one from sources. yes it is quite easy to make your own programs for cortex-m devices with plain gcc, but with gcc it has to be compiled to target a device. with llvm/clang it targets all of them but you need a linker (binutils works nice) – old_timer Feb 10 '17 at 21:33
  • https://github.com/dwelch67/stm32_samples/tree/master/NUCLEO-F411RE cortex-ms all boot the same and are all thumb machines. the chip specific stuff is chip specific so you have to deal with that. we could get into a debate whether it is easier to just program the peripherals directly or learn the api calls of some library. I suggest you try both, and form your own opinion. – old_timer Feb 10 '17 at 21:37
6

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).

bitsmack
  • 16,747
  • 9
  • 52
  • 108
  • 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
  • 1
    @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
  • Where do you find the `mem.ld`, `libs.ld`, and `sections.ld` files? – oxr463 Jul 01 '19 at 00:45
  • 1
    @LucasRamage They are part of the [GNU ARM Eclipse](https://gnu-mcu-eclipse.github.io/) 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. – bitsmack Jul 06 '19 at 00:27
1

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.

MathiasE
  • 479
  • 2
  • 7
1

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.

Peter Mortensen
  • 1,676
  • 3
  • 17
  • 23
dannyf
  • 4,272
  • 1
  • 7
  • 9
1

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

Anton Stafeyev
  • 341
  • 3
  • 13