I've been reading a lot of stuff about using ARM tool chain to build applications for different microcontrollers including ARM cores. Right now, I've been using the fairly easy route with Atmel Studio 7 for xmega devices.

I understand that header files are provided by Atmel Studio 7 for their devices (in my case, the ATSAME70Q21.h or the XMEGA64A3U.h for past projects) which points to all the peripherals available in the microcontroller.

My question is, what is the bare minimum header files required if I have a ARM cortex based microcontroller with it's peripherals? Can I build directly with CMSIS? But as CMSIS seems to be only an API for standard ARM core processors, what happens with the peripherals (like UART, I2C,etc..), do I even need a header file definition for a particular device? If I build over CMSIS, does it mean I could easily port my project from say an Atmel ATSAM to an STM32?

I see these blocks but I don't quite understand how they piece together:

  • The ARM tool chain for compliling
  • Vendor specific header files for peripheral definitions.
  • CMSIS core
  • CMSIS implementations? Where are they?

And let's say a CMSIS implentation doesn't exist, how much am I screwed? Can I write this myself based on the datasheet, or is it just a waste of time?

Quite a lot of questions in this post. That show how much I am confused. I like using Atmel Studio, but I prefer when I can do projets from the bare metal and understand how the piece fit together instead of relying on magic code that could vanish in a future version of the IDE.

  • \$\begingroup\$ This question is too non-specific and broad to fit the strictly narrow mission of stack exchange sites. You most definitely can do everything by hand with the data sheet, but most use at least some vendor or externally sourced files. Typically these things are fairly specific, not only to a vendor but to a sub-family. Much of what you are using in Atmel studio is actually content from the Atmel Software Framework which is available distinct download. Other vendors have their own code library and example packages. \$\endgroup\$ Commented Sep 4, 2018 at 3:02
  • 1
    \$\begingroup\$ Have a look at this minimal project: github.com/fduignan/stm32l011_nucleo_blinky \$\endgroup\$
    – filo
    Commented Sep 4, 2018 at 6:06
  • \$\begingroup\$ I find reading the manual and writing the code myself to be easier and faster than trying to get a library working (and accept the bulk and scary code). But you should try the various approaches, more than once every few years, and determine for a particular project the path you want to take. \$\endgroup\$
    – old_timer
    Commented Sep 5, 2018 at 5:42
  • \$\begingroup\$ Unlike an AVR or a PIC. The core is purchased ip from ARM, its not really an arm microcontroller its an STM32 microcontroller or an ATSAMD microcontroller (with the rest of the part number being as important to the description). A small percentage if any of your program is arm core specific, a great deal of the code is specific to the non-arm logic in the chip or through the chips peripherals to things outside the chip which are also not arm specific at all. \$\endgroup\$
    – old_timer
    Commented Sep 5, 2018 at 5:44
  • \$\begingroup\$ so goes the CMSIS stuff, ARM provides the CMSIS portion related to their logic. The chip vendor provides the chip vendor specific portion. It does seem like you understand this separation. Unless you take it to the MBED level which now implies an operating system where it didnt use to before, I would assume that porting is not going to happen that easily if at all. Even cores with the same name and version can vary from one vendor to another, definitely assume the peripherals are completely incompatible just like AVR vs PIC. \$\endgroup\$
    – old_timer
    Commented Sep 5, 2018 at 5:47

2 Answers 2


This is a nice question. I was also confused when I first started working with ARM-based microcontrollers. You can certainly write code directly using the reference documentation. I do, and in my case, I find it simpler than trying to use the libraries.

On the ARM Web site you will find:

The ARM Cortex-M7 technical reference: https://developer.arm.com/docs/ddi0489/latest/preface

The ARMv7-M architecture reference: https://developer.arm.com/products/architecture/cpu-architecture/m-profile/docs

There is considerable overlap between the above documents, I find myself using the architecture reference manual.

These documents are clearly written, and you will find reference information about the key components that are common to all Cortex-M7 implementations and ARMv7-M implementations (the Cortex-M4 and Cortex-M7 are both ARMv7-M implementations). I used the documents to write the part of my firmware that deals with the ARM processor, interrupts, memory protection, and caches.

You asked about the compiler toolchain. ARM posts current releases of the GNU toolchain for ARM at: https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads

I use the Atom text editor, and configured it to compile using the GNU ARM toolchain. That works very well.

For your specific microcontroller - in this case the Microchip SAM E70 series - the Microchip datasheet describes all the peripherals and registers. You can program directly to that.

In the case of ST Microelectronics STM32 processors, the ST Microelectronics datasheet describes only the component itself. A separate technical reference manual describes the programming details of the peripherals and their associated registers.

When I started, I referred to the CMSIS and vendor library source code when working out the sequence to bring up the microcontroller. Since then, I have not bothered. The reference manuals are sufficient.

You certainly can share source code for the ARM processor between any Cortex-M7 implementation. The Cortex-M7 and Cortex-M4 are close enough that a single set of source code works for both. So, with a little care, your code for the ARM processor itself will work on any Cortex-M4 and Cortex-M7 processor.

The code for the ARM processor core is likely to be a very small part of your software. Most of your microcontroller-specific code will deal with the peripherals.

The Microchip and ST Microelectronics peripheral implementations are not necessarily similar. I glanced at the Microchip SAM E70 USART peripheral description, since recently I have been implementing USART code for the ST Microelectronics STM32L4/4+. The peripherals are very different, I can't imagine that there would be any significant code sharing between firmware for the Microchip SAM E70 and the ST Microelectronics USARTs.

To me, the most confusing code was that which dealt with startup. A reasonable startup sequence is something like:

The first steps deal with the ARM processor core, use the ARM manuals for reference:

  1. Initialize processor (enable floating point instructions, disable and clear caches - the processor reset does not clear the caches, this must be done in firmware).
  2. Enable processor components (caches, MPU, NVIC, etc.)

The following steps deal with C/C++ runtime and with memory layout:

  1. Initialize C/C++ runtime system (static variable initialization, etc.)
  2. Initialize any memory allocation

From this point, standard C/C++ code will run.

The following steps with with the microcontroller peripherals, use the microcontroller reference documentation:

  1. Initialize microcontroller clocks (component-specific). Until this point, the processor has been running on whatever clock is used at reset.
  2. Enable the ARM processor SysTick clock. This clock is part of the ARM architecture (see the ARM manual), but is clocked by the microcontroller clock, so it runs at the correct rate only after the microcontroller clocks have been initialized.
  3. Enable microcontroller peripheral clocks for the peripherals you want to access.

Now you can access each of the peripherals of interest.

As a detail, the microcontroller may offer a clock output (ST Microelectronics STM32 processors call this 'RCC MCO'). For debugging, I find it useful to enable this specific pin during clock initialization (which on some microcontrollers requires enabling the associated GPIO peripheral clock), because then I can use an oscilloscope to monitor the clock being used. I can see each clock come up at the correct frequency. After the clocks are running properly, everything else is easy.

  • \$\begingroup\$ That is great! So much information, pretty much exactly what I was looking for. So I can just basically add libraries as I go along and I see fit based on the basic setup with the ARM core? Something like the CMSIS DSP Lib that I will need. \$\endgroup\$ Commented Sep 4, 2018 at 4:16
  • \$\begingroup\$ Also, is there any useful implementations in the CMSIS core or writing to peripheral registers is just that easy "by hand"? \$\endgroup\$ Commented Sep 4, 2018 at 4:19
  • \$\begingroup\$ I'm ok with finding registers to write stuff to them to make the microcontroller do something but implementing FFT by myself would seems like a waste of time considering the CMSIS DSP lib exists. I want to do the simple things bare metal, but for more complex existing algorithm, I'd like to be able to use libraries. As I understand the CMSIS DSP lib is only dependent on the ARM Cortex core and nothing related to specific peripheral, so I should be good adding it to the project later? \$\endgroup\$ Commented Sep 4, 2018 at 4:23
  • 1
    \$\begingroup\$ I am not really sure how to answer that. I find working directly with the hardware very easy. I don't know about the DSP library. \$\endgroup\$
    – D. Brown
    Commented Sep 4, 2018 at 4:40
  • \$\begingroup\$ You are possibly right that the DSP library which in the CMSIS scheme would be written by ARM for a core and is not really dependent on peripherals would be something that could be carved out and use more so than something that has a memory address space and registers and that CMSIS baggage. But you would just have to look for yourself. \$\endgroup\$
    – old_timer
    Commented Sep 5, 2018 at 5:39

Yes, you can add definitions for a few simple registers 'by hand'. It may not make sense for a real system though since you may end up duplicating a lot of code.

Here is the header for Cortex-M3 Designstart within the mbed repository. This is an FPGA based design with only a handful of peripherals. Since it is quite stripped down, it makes a good reference to see what the minimum required is.


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.