Editor’s Note: Excerpted from The Designer's Guide to the Cortex-M Processor Family , by Trevor Martin, the author provides an in-depth tutorial on the ARM Cortex Microcontroller Software Interface Standard (CMSIS) and how to use it to import and integrate source code from multiple sources during the development of embedded systems software applications .
The widespread adoption of the Cortex-M processor into general purpose microcontrollers has led to two rising trends within the electronics industry. First of all the same processor is available from a wide range of vendors each with their own family of microcontrollers. In most cases, each vendor creates a range of microcontrollers that span a range of requirements for embedded systems developers.
This proliferation of devices means that as a developer you can select a suitable microcontroller from many hundreds of devices while still using the same tools and skills regardless of the silicon vendor. This explosive growth in Cortex-M-based microcontrollers has made the Cortex-M processor the de facto industry standard for 32-bit microcontrollers and there are currently no real challengers.
Figure 1: CMSIS compliant software development tools and middleware stacks are allowed to carry the CMSIS logo.
The flip side of the coin is differentiation. It would be possible for a microcontroller vendor to design their own proprietary 32-bit processor. However, this is expensive to do and also requires an ecosystem of affordable tools and software to achieve mass adoption. It is more cost effective to license the Cortex-M processor from ARM and then use their own expertise to create a microcontroller with innovative peripherals.
There are now more than 10 silicon vendors shipping Cortex-M-based microcontrollers. While in each device the Cortex-M processor is the same, each silicon manufacturer seeks to offer a unique set of user peripherals for a given range of applications.
This can be a microcontroller designed for low-power applications, motor control, communications, or graphics. This way a silicon vendor can offer a microcontroller with a state-of-the-art processor that has wide development tools support while at the same time using their skill and knowledge to develop a microcontroller featuring an innovative set of peripherals.
Figure 2: Cortex-based microcontrollers can have a number of complex peripherals on a single chip. To make these work you will need to use some form of third-party code. CMSIS is intended to allow stacks from different sources to integrate together easily.
These twin factors have led to a vast 'cloud' of standard microcontrollers with increasingly complex peripherals as well as typical microcontroller peripherals such as USART, I2C, ADC, and DAC. A modern high-end microcontroller could well have a HostDevice USB controller, Ethernet MAC, SDIO controller, and LCD interface. The software to drive any of these peripherals is effectively a project in itself, so gone are the days of a developer using an 816-bit microcontroller and writing all of the application code from the reset vector.
To release any kind of sophisticated product it is almost certain that you will be using some form of third-party code in order to meet project deadlines. The third-party code may take the form of example code, an open source or commercial stack or a library provided by the silicon vendor. Both of these trends have created a need to make C-level code more portable between different development tools and different microcontrollers. There is also a need to be able to easily integrate code taken from a variety of sources into a project. In order to address these issues, a consortium of silicon vendors and tools vendors has developed the CMSIS (seeMsys) for short.
The main aim of CMSIS (Cortex Microcontroller Software Interface Standard) is to improve software portability and reusability across different microcontrollers and toolchains. This allows software from different sources to integrate seamlessly together. Once learned, CMSIS helps to speed up software development through the use of standardized software functions.
At this point it is worth being clear about exactly what CMSIS is. CMSIS consists of five interlocking specifications that support code development across all Cortex-M-based microcontrollers. The four specifications are as follows: CMSIS core, CMSIS RTOS, CMSIS DSP, CMSIS SVD, and CMSIS DAP.
Figure 3: CMSIS consists of a several separate specifications (CORE, DSP, RTOS, SVD, and DAP) that make source code more portable between tools and devices.
It is also worth being clear what CMSIS is not. CMSIS is not a complex abstraction layer that forces you to use a complex and bulky library. CMSIS does not attempt to 'dumb down' peripherals by providing standard profiles that make different manufacturers’ peripherals work the same way. Rather, the CMSIS core specification takes a very small amount of resources (about 1k of code and just 4 bytes of RAM) and standardizes the way you access the Cortex-M processor and microcontroller registers.
Furthermore, CMSIS does not really affect the way you develop code or force you to adopt a particular methodology. It simply provides a framework that helps you to integrate third-party code and reuse the code on future projects. Each of the CMSIS specifications is not that complicated and can be learned easily. The full CMSIS specifications can be downloaded from the URL www.onarm.com . Each of the CMSIS specifications are integrated into the MDK-ARM toolchain and the CMSIS documentation is available from the online help.
The core specification provides a minimal set of functions and macros to access the key Cortex-M processor registers. The core specification also defines a function to configure the microcontroller oscillators and clock tree in the startup code so the device is ready for use when you reach main(). The core specification also standardizes the naming of the device peripheral registers. The CMSIS core specification also standardizes support for the instrumentation trace during debug sessions.
The CMSIS RTOS specification provides a standard API for an RTOS.This is in effect a set of wrapper functions that translate the CMSIS RTOS API to the API of the specific RTOS that you are using. The Keil RTX RTOS was the first RTOS to support the CMSIS RTOS API and it has been released as an open source reference implementation. RTX can be compiled with both the GCC and IAR compilers It is licensed with a three-clause Berkeley Software Distribution (BSD) license that allows its unrestricted use in commercial and noncommercial applications.
The Cortex-M4 is a 'digital signal controller' with a number of enhancements to support DSP algorithms. Developing a real-time DSP system is best described as a 'nontrivial pastime' and can be quite daunting for all but the simplest systems. To help mere mortals include DSP algorithms in Cortex-M4 and Cortex-M3 projects, CMSIS Includes a DSP library that provides over 60 of the most commonly used DSP mathematical functions. These functions are optimized to run on the Cortex-M4 but can also be compiled to run on the Cortex-M3.
CMSIS SVD and DAP
One of the key problems for tools vendors is to provide debug support for new devices as soon as they are released. The debugger must provide peripheral view windows that show the developer the current state of the microcontroller peripheral registers. With the growth in both the numbers of Cortex-M vendors and also the rising number and complexity of on chip peripherals it is becoming all but impossible for any given tools vendor to maintain support for all possible microcontrollers.
To overcome this hurdle, the CMSIS debug specification defines a 'system viewer description' (SVD) file. This file is provided and maintained by the silicon vendor and contains a complete description of the microcontroller peripheral registers in an XML format. This file is then imported by the development tool, which uses it to automatically construct the peripheral debug windows for the microcontroller. This approach allows full debugger support to be available as new microcontrollers are released.
Figure 5: CMSIS DAP allows for interoperability between different vendors, software, and hardware debuggers.
The CMSIS DAP specification defines the interface protocol for a hardware debug unit that Sits between the host PC and the debug access port( DAP)of the microcontroller. This allows any software tool chain that supports CMSIS DAP to connect to any hardware debug unit that also supports CMSIS DAP. There are an increasing number of very-low-cost evaluation boards that ontain an integral debugger. Often this debugger supports a selected toolchain. With CMSIS DAP such a board could be used with any compliant development tool.Foundations of CMSIS
The CMSIS core specification provides astandard set of low-level functions, macros, and peripheral registerdefinitions that allow your application code to easily access theCortex-M processor and microcontroller peripheral registers. Thisframework needs to be added to your code at the start of a project. Thisis actually very easy to do as the CMSIS core functions are very much apart of the compiler toolchain.
WhileCMSIS is important for providing a standardized software interface forall Cortex-M Microcontrollers it is also interesting for embeddeddevelopers because it defines a consistent set of C coding rules. Whenapplied, these coding rules generate clear unambiguous C code. Thisapproach is worth studying as it embodies many of the best practicesthat should be adopted when writing the C source code for your ownapplication software.
The main backbone of theCMSIS coding rules is a set of coding guidelines called MISRA Cpublished by MIRA. MIRA stands for 'Motor Industry Research Agency' andis located near Rugby in England. It is responsible for many of theindustry standards used by the UK motor industry. In 1998, its softwaredivision the Motor Industry Software Research Agency released the firstversion of its coding rules formally called “MISRA guidelines for theuse of C in vehicle electronics.”
Theoriginal MISRA C specification contained 127 rules which attempted toprevent common coding mistakes and resolve gray areas of the ANSI Cspecification when applied to embedded systems. Although originallyintended for the automotive industry MISRA C has found acceptance in thewider embedded systems community. In 2004, a revised edition of MISRA Cwas released with the title “MISRA C coding guidelines for the use of Cin safety systems.” This change in the title reflects the growingadoption of MISRA C as a coding standard for general embedded systems.
Oneof the other key attractions of MISRA C is that it was written byengineers and not by computer scientists. This has resulted in a clear,compact, and easy to understand set of rules. Each rule is clearlyexplained with examples of good coding practice. This means that theentire coding standard is contained in a book of just 106 pages whichcan easily be read in an evening. A typical example of a MISRA C rule isshown below:
Rule 13.6(required) Numeric variables beingused within a for loop for iteration counting shall not be modified inthe body of the loop.
Loop counters shall not be modified inthe body of the loop. However, other loop control variables representinglogical values may be modified in the loop. For example, a flag toindicate that something has been completed which is then tested in the'for' statement.
Flag = 1;
For ((I=0;(i<5) && (flag ==1);i++)
Flag = 0; /* Compliant allows early termination of the loop */
i =i+3; /*Not Compliant altering the loop counter */
Wherepossible, the MISRA C rules have been designed so that they can bestatically checked either manually or by a dedicated tool. The MISRA Cstandard is not an open standard and is published in paper andelectronic form on the MIRA Web site. In addition to the MISRA Cguidelines, CMSIS enforces some additional coding rules. To prevent anyambiguity in the compiler implementation of standard C types CMSIS usesthe data types defined in the ANSI C header file stdint.h.
Thetypedefs ensure that the expected data size is mapped to the correctANSI type for a given compiler. Using typedefs like this is a goodpractice, as it avoids any ambiguity about the underlying variable size,which may vary between compilers particularly if you are migrating codebetween different processor architectures and compiler tools.
CMSISalso specifies IO type qualifiers for accessing peripheral variables.These are typedefs that make clear the type of access each peripheralregister has. While this does not provide any extra functionality foryour code it provides a common mechanism that can be used by staticchecking tools to ensure that the correct access is made to eachperipheral register.
Muchof the CMSIS documentation is autogenerated using a tool calledDoxegen. This is a free download released under a GNU Public (GPL)license. While Doxegen cannot actually write the documentation for youit does do much of the dull boring stuff for you (leaving you to do theexiting documentation work).
Doxegenworks by analyzing your source code and extracting declarations andspecific source code comments to build up a comprehensive 'objectdictionary' for your project. The default output format for Doxegen is abrowsable HTML but this can be converted to other formats if desired.The CMSIS source code comments contain specific tags prefixed by the @symbol, for example, @brief. These tags are used by Doxegen to annotatedescriptions of the CMSIS functions.
* @brief Enable Interrupt in NVIC Interrupt Controller
* @param IRQn interrupt number that specifies the interrupt
* Enable the specified interrupt in the NVIC Interrupt Controller.
* Othersettings ofthe interruptsuchas priority are not affected.
Whenthe Doxegen tool is run it analyzes your source code and generates areport containing a dictionary of your functions and variables based onthe comments and source code declarations.
The CMSIS corefunctions can be included in your project through the addition of threefiles. These include the default startup code with the CMSIS standardvector table. The second file is the system_ ,device..c file, whichcontains the necessary code to initialize the microcontroller systemperipherals. The final file is the device include file, which importsthe CMSIS header files that contain the CMSIS core functions and macros.
Figure7: The CMSIS core standard consists of the device startup, system Ccode, and a device header. The device header defines the deviceperipheral registers and pulls in the CMSIS header files. The CMSISheader files contain all of the CMSIS core functions.
Startup Code. The startup code provides the reset vector, initial stack pointer value, and a symbol for each of the interrupt vectors.
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
Whenthe processor starts, it will initialize the MSP by loading the valuestored in the first 4 bytes of the vector table. Then it will jump tothe reset handler.
EXPORT Reset_Handler [WEAK]
LDR R0, =SystemInit
LDR R0, =__main
Part 2: The CMSIS Core structure
Trevor Martin is Senior Technical Specialist within Hitex UK. Over the 20 years hehas worked at Hitex UK, hevor has worked with a wide range ofmicrocontrollers and associated development tools. Since the launch ofthe Cortex-M3 processor in 2004, Trevor has contributed numerousarticles and application notes for many of the leading Cortex-M basedmicrocontrollers.
Used with permission from Newnes, an imprint of Elsevier, Copyright 2013, this article was excerpted from The Designer's Guide to the Cortex-M Processor Family , by Trevor Martin.