Are you considering switching MCU platform in your embedded project? There might be several reasons why switching out the MCU ecosystem can become attractive - or even necessary - e.g. supply chain obstruction due to occurences beyound our control, pricing, changing requirements, etc. This may happen to any embedded project and if it does the ability to switch vendor with manageable effort can be a significant advantage. Using a suitable software architecture and simple version control principles it is possible to arrange embedded software in such a manner that it becomes easy to switch between vendors or even manage several vendors at the same time. # Multi Vendor Embedded Development A straight forward way to support multi vendor embedded development is to organize the embedded source code into 3 distinct portions. 1) Vendor specific code (VSC) 2) Vendor agnostic code (VAC) 3) A glue layer to bind it together ## Vendor Specific Code This code depends specifically on the vendor supplied MCU and ecosystem. This code can be viewed as a board support package (BSP) and is usually part of libraries and frameworks supplied by the vendor to enable the interfacing with the specific MCU or MCU family. The VSC is managed by vendor specific tooling such as a preferred IDE (e.g Eclipse, IAR Embedded Workbench, Keil embedded workbench, ect) used for development and vendor specific cross compilers and debuggers. ## The Vendor Agnostic Code (VAC) This code models the business logic of the software solution. In here the user requirements and overall general functionality of the solution is implemented. The VAC is generic and does not depend on the vendor specific compiler, hardware, configuration, IDE or build system. This distinction between VSC and VAC is a matter of definition: If a piece of code have to depend on the vendor ecosystem it is VSC. If it does not have any real dependencies to the vendor ecosystem it is by definition part of the VAC. In any given embedded project some code will be vendor specific, while some code will not. For some projects it may be, that the majority of the code is inherently vendor specific, for other embedded projects the reverse may be the case and nearly all code is naturally vendor agnostic. The more code that is vendor agnostic the bigger the advantage of separating the codebase into VSC and VAC. ## The Glue layer This layer ties the VAC and VSC together. The VAC can through a series of interfaces interact with the VSC to interface to the hardware as illustrated in the figure below << Figure >> These interfaces usually appears as at least three types, - The Hardware Abstraction Layer (HAL) contains interface functions to interact with the hardware such as sensors or actuators - The OS Abstraction Layer (OS AL) exposes interface functions to e.g. start threads or send events, read/write files (flash) and similar - The Runtime Abstraction Layer (RAL) exposes interface functions related to the runtime system (memory management, interrupt handling, stack maniulation, etc) For a given embedded project there may be more or less of these interfaces but the above examples illustrate what one may encounter in many typical scenarios. Organizing the full code base into VAC, VSC and a the glue layer introduces an indirection when interfacing to hardware, but this indirection can be implemented using the linker, and that reduces the cost of the indirection to be very low or even zero. In other words, the glue layer is not a runtime indirection that requires a lookup table, but rather a statically compiled jump that is resolved by the linker at compile time. # Code organization If code is divided into VAC and VSC and a glue layer, it now becomes trivially possible to mange several coexisting vendors. The way to do it is to place the VSC into a version control parent project and include the VAC as a version control child- or submodule. The main entry point is in the VSC and during start up it will - at the appropriate place - call a single function exposed by the VAC, namely the 'mainRoutine' entry point (possibly supplying some arguments as suggested in the illustration above). The VAC can from here on interface with the VSC through the glue layer. For each vendor there will be a specific version control parent project, that contains vendor specific buildfiles and can be opened in the vendor specific IDE and compiled using the vendor specific cross compilers. All these vendor specific projects will contain the same VAC as a version control submodule. In this way we can imagine a developer opening the project in e.g. Eclipse - augmented with suitable plugins supplied by vendor A - and at the same time the developer can open another project in the IAR embedded workbench preferred by vendor B. These two projects will be significantly different using entirely different build methods and compiler tool chains and BSPs. But, they will contain the same VAC submodule. Activating the build process in both IDEs will result in two firmwares, one for the vendor A MCU and one for the vendor B MCU. # Feasibility Such an approach is feasible if a significant portion of the full code base can be placed in the VAC. In that case, all code classified as VAC can be trivially ported to new vendor MCUs just by implementing a new glue layer. If, for another project, the majority of the code has to be classified as VSC, then there is not much gained by performing the separation. Also, it requires continuous effort from architects and developers to maintain the separation between the VAC and the VSC. If e.g. a developer adds a dependency from the mainRoutine - inside the VAC - to a vendor specific resource in the BSP, this single small change immediately turns all VAC into VSC. The "Host" vendor Even in the case where there is no current reason to switch vendor, there are still good reasons to follow the principles of Multi Vendor Embedded Development: By viewing the development host (e.g. Windows or Linux) as an additional vendor and creating a BSP (which will be basically some subset of posix) to implement a glue layer for the Linux/Windows, it becomes possible to run the VAC on the host development PC. This is also known as "Dual Targeting" - see James W. Grenning - but here formulated as an additional vendor in a Multi Vendor Embdedded Development setup. Having the ability to run the VAC on the development host has the advantages of enabling development without interfacing to the actual hardware and by enabling running regression tests in the cloud or on the development host. Conclusing The principle of Multi Vendor Embedded Development suggests dividing embedded code bases into vendor agnostic and vendor specific parts and tie them together by a glue layer. If the vendor agnostic part is placed in its own version control submodule it can be included into several vendor specific parent projects and compiled for several MCUs. This reduces dependency on any given vendor. The host OS can further be viewed as a seperate vendor. This enables host based development - without having to deploy to actual hardware - and it enables cloud based regression testing of the vendor agnostic part of embedded software.