Class Libraries
About this document
This document describes the design and organization of .NET nanoFramework Class Libraries, offers some explanation on the choices that were made and how to add a new Class Library. The examples bellow are related with ChibiOS (which is the currently reference implementation for .NET nanoFramework).
Libraries
Follow the list of the existing libraries, respective NuGet package and CMake enable option:
Other libraries
Board Support Packages libraries
Distribution strategy
To ease the burden of distributing and updating the class libraries we've choose to use Nuget to handle all this. It has the added benefit of dealing with the dependency management, version and such.
So, for each class library, there is a Nuget package that includes the assembly and documentation files. The Nuget package takes care of making sure that the required dependency(ies) and correct version(s) are added to a managed (C#) project, making a developer's life much easier.
How to add a new class library
Follow the procedure to add a new class library to a .NET nanoFramework target image.
The example is for adding System.Device.Gpio library.
In Visual Studio start a new project for a .NET nanoFramework C# Class library. Source code here
Implement all the required methods, enums, properties in that project. It's recommended that you add XML comments there (and enable the automated documentation generation in the project properties).
Add the NuGet packaging project to distribute the managed assembly and documentation. We have a second NuGet package that includes all the build artefacts, generated stubs, dump files and such. This is to be used in automated testing and distribution of follow-up projects or build steps.
Upon a successfully build of the managed project the skeleton with the stubs should be available in the respective folder. Because .NET nanoFramework aims to be target independent, the native implementation of a class library can be split in two parts:
- Declaration and common code bits (these always exist) inside the
src
folder. This is the place where the stubs must be placed:- Common System.Device.Gpio.
- The specific implementation bits that are platform dependent and that will live 'inside' each platform RTOS folder:
- ChibiOS System.Device.Gpio.
- ESP32 FreeRTOS System.Device.Gpio.
- TI-RTOS System.Device.Gpio.
- Declaration and common code bits (these always exist) inside the
Add the CMake as a module to the modules folder here. The name of the module should follow the assembly name (FindSystem.Device.Gpio.cmake). Mind the CMake rules for the naming: start with Find followed by the module name and cmake extension. The CMake for the System.Device.Gpio module is here.
In the CMake FindNF_NativeAssemblies.cmake add an option for the API. The option name must follow the pattern API_namespace. The option for System.Device.Gpio is API_System.Device.Gpio.
In the CMake NF_NativeAssemblies.cmake find the text
WHEN ADDING A NEW API add the corresponding block below
and add a block for the API. Just copy/paste an existing one and replace the namespace with the one that you are adding.Update the CMake presets file (or files, if this is to be added to multiple targets) e.g. for the ST_STM32F769I_DISCOVERY here to include the respective option. For the System.Device.Gpio example you would add in the cacheVariables collection the following entry: "API_System.Device.Gpio" : "ON".
If the API requires enabling hardware or SoC peripherals in the target HAL/PAL make the required changes to the appropriate files. For System.Device.Gpio in ChibiOS there is nothing to enable because the GPIO subsystem is always enabled. In contrast, for the System.Device.Spi, the SPI subsystem has to be enabled at the halconf.h file and also (at driver level) in mcuconf.h the SPI peripherals have to be individually enabled (e.g.
#define STM32_SPI_USE_SPI1 TRUE
).Note: To ease the overall configuration of an API and related hardware (and when it makes sense) the API option (API_System.Device.Gpio) can be extended to automatically enable the HAL subsystem. This happens with the System.Device.Spi API. The CMake option is mirrored in the general CMakeLists.txt in order to be used in CMakes and headers. This mirror property is
HAL_USE_SPI_OPTION
. It's being defined here and not in the individual halconf.h files as usual. To make this work the CMake property has to be added to the CMake template file of the platform target_platform.h.in.When adding/enabling new APIs and depending on how the drivers and the library are coded, some static variables will be added to the BSS RAM area. Because of that extra space that is taken by those variables the Managed Heap size may have to be adjusted to make room for those. To do this find the
__clr_managed_heap_size__
in the general CMakeLists.txt of that target and decrease the value there as required.Some APIs depend of others. This happens for example with System.Device.Gpio that requires nanoFramework.Runtime.Events in order to generate the interrupts for the changed pin values. To make this happen the option to include the required API(s) has to be enabled in the main CMakeLists.txt inside the if clause of the dependent API. Just like if the option was enabled at the CMake command line. Check this by searching for
API_nanoFramework.Runtime.Events
inside theif(API_System.Device.Gpio)
.
How to include a class library in the build
To include a class library in the build for a target image you have to add to the CMake an option for the API. For the System.Device.Gpio example the option would be -DAPI_System.Device.Gpio=ON
.
You can also add this to your own CMakePresets.json
/ CMakeUserPresets.json
file.
To exclude a class library just set the option to OFF or simply don't include it in the command.