The Cortex Microcontroller Software Interface Standard (CMSIS) is a vendor-independent hardware abstraction layer for Arm Cortex-M and Cortex-A processors and defines generic tool interfaces.
The CMSIS-Pack standard specifies a delivery mechanism for device support and software components. The CMSIS-Pack system is now implemented in several leading development toolkits such as:
The ability to distribute software components makes CMSIS-Packs attractive for software platform providers. The following will focus on the benefits of CMSIS specifically for software components.
Well-defined software components, such as an RTOS, networking stack, driver interfaces, or DSP algorithms, are building blocks for user applications that significantly reduce the effort for software developers.When directly using the source code of a software component in the user application, the maintenance of a product becomes difficult. Frequently, the initial source of that component is unclear, information about the related files, configuration settings, or original documentation is lost.
The CMSIS-Pack system solves several typical user problems:
The integration of the CMSIS-Pack system into various IDEs simplifies the usage of software components. Generic software components can therefore gain a wider adoption.
A software component encapsulates a set of related functions. For bare-metal microcontroller development C/C++ is the de-facto language of choice. However, software components can also contain object code, assembler files, header files, or libraries. The interfaces of software components should be defined with API headers to make them substitutable by other compatible components at design time.
In addition, CMSIS software components should contain documentation for the software component. They may provide user code templates that give a starting point for the application developer, and can have optional debug view descriptions for debuggers.
CMSIS software components can also refer to multiple interfaces of other software components. This could be also a hardware abstraction layer for a device peripheral.
Configuration files contain application specific parameters for a software component. These files are typically copied to the user project workspace; all other files are not modified by the user and can remain in a separate location which avoids that a project workspace is polluted by many source files that should be considered as “black-box” elements by the application programmer.
To reference software components, CMSIS specifies naming conventions that have the following elements:
Optionally, a software component may have additional attributes:
Software components can reference other software components using conditions which is illustrated in this diagram:
A condition describes dependencies on device, processor, and tool attributes as well as the presence of other components. The condition can be used to ensure that specific software components are either present in the system or can prevent that illegal combinations of software components are chosen by the user.
A common problem of the software industry: API headers that are defined for a software component evolve over time, but the various implementations that consume these interfaces continue to use outdated header files, which frequently causes inconsistencies when drivers are independently developed.
The CMSIS-Pack system allows therefore a central API definition that shares header file and documentation of an API interface.
This single API interface definition ensures consistency when it is used across multiple implementations that consume the interface. The API interface definition can be distributed separately or as part of the software component that consumes this interface.
An example is the CMSIS-Driver pack that contains various Ethernet and Flash drivers – all compatible with the CMSIS-Driver APIs that are published in the CMSIS Pack.
Many software developers rely on an IDE for project creation and management. All popular IDEs support today the CMSIS-Pack concept and offer functionality to build projects using software components efficiently.
For example, the IDEs use the component conditions to refer other required software components for the project:
In this example, we selected a USB software component that requires that for example a real-time operating system is present. The Validation Output highlights during component selection such required software components and even suggests possible selections. During set up of the application specific run-time environment, this ensures that requirements are met. The software developer can then concentrate on the actual application development.
Software components can refer the related code templates that help application developers to get started with the application development. To use a code template, just right-click the project and select to add a code template:
In the following dialog, select the user code template that you wish to use:
IDEs using the meta-data from the XML description, make it easy to access documentation that is specific for the component version that you are using. Simply click on the link that is shown in the run-time environment manager:
Configuration files are commonly used to set certain parameters of a software component. Often, configuration files are complex, with too many #define statements. Using simple source code annotations for the Configuration Wizard, you can create a meaningful user interface. IDEs read the annotated file and display it in a user friendly way:
When you update a software component, the IDE makes you aware of potentially outdated configuration files for a software component. In this example, the USBD_Config_0.c file should be updated (marked by the yellow file icon). You can either update the file directly or use your favorite merge tool to examine the differences between the configuration file versions.
Frequently, the behaviour or features of a software component depend on the presence of other software components in the system. For example, a network stack can interface to Ethernet or serial PPP (UART). Depending on the presence of interface components, the implementation may behave differently.
To simplify application configuration, the file RTE_Components.h is generated before the project build step and contains the inventory of all selected components. For each selected software component, it contains #define statements that are specified by the component meta data. The following example shows a sample RTE_Components.h file:
/* Auto generated Run-Time-Environment Component Configuration File *** Do not modify ! *** */ #ifndef RTE_COMPONENTS_H #define RTE_COMPONENTS_H /* Define the Device Header File: */ #define CMSIS_device_header "stm32f10x.h" #define RTE_Network_Interface_ETH_0 /* Network Interface ETH 0 */ #define RTE_Network_Socket_BSD /* Network Socket BSD */ #define RTE_Network_Socket_TCP /* Network Socket TCP */ #define RTE_Network_Socket_UDP /* Network Socket UDP */ #endif /* RTE_COMPONENTS_H */
The typical usage of the RTE_Components.h file is in header files to control features that depend on the inclusion to other software components. For example:
#include "RTE_Components.h" #ifdef RTE_Network_Interface_ETH_0 // if component is included #include "Net_Config_ETH_0.h" // add related configuration file #endif
When using software components, you can use the conditions to automatically resolve dependencies on other components, as we have seen. You can use this to combine components for one project in a certain way while combining them differently for another project. In the following example, we are using a network stack to transfer data via Ethernet. The network stack requires a MAC and PHY to do this. The selected device from silicon vendor A that contains an on-chip MAC, thus only requiring a PHY to be selected:
You can copy the project, select a different device from silicon vendor B for example and let the run-time environment manager do the exchange of the components. As the new devices doe not have an on-chip MAC, you need to select a different component to fulfill the requirement for the network stack:
This reduces the development time drastically, as the developer does not need to care for the correct dependency between software components, but can concentrate on the implementation of his own application code.
Creating a CMSIS-Pack containing software components is an easy task. All you need to do is to follow these steps:
The CMSIS-Pack concept also specifies a release mechanism that simplifies the integration of software components into complex applications. To release software components as a pack follow these steps:
The CMSIS-Pack documentation on GitHub explains the details and contains a step-by-step tutorial.
CMSIS-Packs containing software components ease the life of the developer. Many tedious tasks when working with components are automatically taken care for by the IDE using the mechanisms that are built-in into a pack. Required changes in the project when switching from one component revision to another or from one device to another are flagged by the component manager and demand only little attention. Portability of the overall code increases and time-to-market is reduced. Using APIs, software component providers can ensure that their components work in different software and hardware environments and can extend the reach of their component dramatically.
More about CMSIS-Pack