Table of Contents

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).


Follow the list of the existing libraries, respective NuGet package and CMake enable option:

Class Library Version CMake option
Base Class Library (also know as mscorlib) NuGet (always included)
Base Class Library (without Reflection) NuGet (always included, -DNF_FEATURE_SUPPORT_REFLECTION=OFF)
nanoFramework.Device.Bluetooth NuGet -DAPI_nanoFramework.Device.Bluetooth=ON
nanoFramework.Device.Can NuGet -DAPI_nanoFramework.Device.Can=ON
nanoFramework.Device.OneWire NuGet -DAPI_nanoFramework.Device.OneWire=ON
nanoFramework.Graphics NuGet -DAPI_nanoFramework.Graphics=ON
nanoFramework.GiantGecko.Adc NuGet -DAPI_nanoFramework.GiantGecko.Adc=ON
nanoFramework.M5Stack NuGet -DAPI_nanoFramework.M5Stack=ON
nanoFramework.Hardware.Esp32 NuGet -DAPI_Hardware.Esp32=ON
nanoFramework.Hardware.Esp32.Rmt NuGet -DAPI_Hardware.Esp32.Rmt=ON
nanoFramework.Hardware.GiantGecko NuGet -DAPI_Hardware.GiantGecko=ON
nanoFramework.Hardware.Stm32 NuGet -DAPI_Hardware.Stm32=ON
nanoFramework.Hardware.TI NuGet -DAPI_Hardware.TI=ON
nanoFramework.ResourceManager NuGet -DAPI_nanoFramework.ResourceManager=ON
nanoFramework.Runtime.Events NuGet (always included)
nanoFramework.Runtime.Native NuGet (always included)
nanoFramework.Networking.Sntp NuGet (included when network option is ON)
nanoFramework.TI.EasyLink NuGet -DAPI_nanoFramework.TI.EasyLink=ON
System.Device.Adc NuGet -DAPI_System.Device.Adc=ON
System.Device.Dac NuGet -DAPI_System.Device.Dac=ON
System.Device.I2c NuGet -DAPI_System.Device.I2c=ON
System.Device.I2s NuGet -DAPI_System.Device.I2s=ON
System.Device.Gpio NuGet -DAPI_System.Device.Gpio=ON
System.IO.FileSystem NuGet -DAPI_System.IO.FileSystem=ON
System.IO.Ports NuGet -DAPI_System.IO.Ports=ON
System.IO.Streams NuGet -DAPI_System.IO.Streams=ON
System.Device.Pwm NuGet -DAPI_System.Device.Pwm=ON
System.Device.Spi NuGet -DAPI_System.Device.Spi=ON
System.Device.WiFi NuGet -DAPI_System.Device.WiFi=ON
System.Device.UsbStream NuGet -DAPI_System.Device.UsbStream=ON
Windows.Storage.Streams NuGet -DAPI_=ON
System.IO.FileSystem NuGet -DAPI_System.IO.FileSystem=ON
System.Collections NuGet no native code
System.Math NuGet -DAPI_System.Math=ON
System.Net NuGet -DAPI_System.Net=ON
System.Net.Http NuGet no native code
System.Net.Http.Client NuGet no native code
System.Net.Http.Server NuGet no native code
System.Net.Sockets.UdpClient NuGet no native code
System.Net.Sockets.TcpClient NuGet no native code
System.Runtime.Serialization NuGet no native code
System.Text NuGet no native code
System.Text.RegularExpressions NuGet no native code
System.Threading NuGet no native code

Other libraries

Class Library Version
AMQP Net Lite NuGet
AMQP Net Lite (micro) NuGet
nanoFramework.Azure.Devices NuGet
nanoFramework.Aws.IoTCore.Devices NuGet
nanoFramework.Logging NuGet
nanoFramework.Json NuGet
nanoFramework.m2mqtt NuGet
nanoFramework.SignalR.Client NuGet
nanoFramework.TestFramework NuGet
nanoFramework.WebServer NuGet
nanoFramework.DependencyInjection NuGet
nanoFramework.Hosting NuGet

Board Support Packages libraries

Class Library Version
nanoFramework.M5Stack NuGet
nanoFramework.M5Stick NuGet
nanoFramework.M5StickCPlus NuGet
nanoFramework.M5Core2 NuGet
nanoFramework.AtomLite NuGet
nanoFramework.AtomMatrix NuGet
nanoFramework.Fire NuGet
nanoFramework.MagicBit NuGet

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.

  1. In Visual Studio start a new project for a .NET nanoFramework C# Class library. Source code here

  2. 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).

  3. 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.

  4. 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:
    • The specific implementation bits that are platform dependent and that will live 'inside' each platform RTOS folder:
  5. 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.

  6. 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.

  7. 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.

  8. 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".

  9. 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

  10. 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.

  11. 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 the if(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.