Mistake on this page? Email us

Porting Pelion Device Management Client on new target SDK

This section explains how to port the Platform Abstraction Layer (PAL) APIs and prepare a standalone build system for a new target SDK. See Porting devices for more detail.

The complete porting of Device Management Client has these steps:

  1. Adapt the target SDK to existing client build system and port RTOS and lwIP component for Device Management Client while running storage over RAM.
  2. Port the KVStore implementation of Device Management Client over target SDK storage implementation (either internal flash or external flash) to enable persistant storage of Device Management Client credentials on the hardware.
  3. Port Device Management Client to adapt to target SDK's bootloader and update storage to enable FOTA feature.

Note: Make sure you follow these steps in the order they appear.

Adapt target SDK to build system

The initial steps to porting Device Management Client to a new SDK are:

  1. Get a new SDK.
  2. Add the SDK to the Device Management Client build system to compile and link Device Management Client with SDK libraries.

Port RTOS and lwIP component with RAM storage

After you have finished adapting the SDK:

  1. Implement porting layers to run the Device Management Client application on the target SDK.
  2. Test ported components individually.
  3. Run the Device Management Client example application over the target SDK.

For reference, use NXP's MCUXpresso SDK to demonstrate the steps.

Adding a new SDK to the build system

To add a new SDK:

  1. Download your target SDK package from its official site or GitHub repository.

    For this guide, download NXP's MCUXpresso SDK for LPCXpresso54628, for the Arm GCC toolchain and Linux environment.

  2. Clone the Device Management Client example:

    git clone https://github.com/PelionIoT/mbed-cloud-client-example.git

  3. Go to mbed-cloud-client-example/pal-platform folder and create a new folder <target_sdk_name> under SDK.

    In the example, it is LPCXpresso54628.

  4. Copy the downloaded target SDK's directory under the new folder. The structure would look like pal-platform/SDK/<target_sdk_name>/SDK_<target_sdk_folder>.

    For MCUXpresso SDK, it would be pal-platform/SDK/LPCXpresso54628/SDK_LPCXpresso54628.

  5. Add information about this structure to pal-platform/pal-platform.json. This utility script deploys and generates platform-dependent files needed to build and run non-Mbed OS applications. It can run on both Linux and Windows. Detailed explaination on this is available here

    An example of the pal-platform/pal-platform.json file for Xpresso SDK for LPCXPresso54628:

      "LPC54628_NXP": {
        "comment": "Extra comments\nfor the instructions",
        "device": {
              "name": "LPC54628"
            },
        "os": {
            "name": "NXP"
        },
        "sdk": {
          "name": "LPCXpresso54628",
          "version": "2.7.0"
        }
      },
    
    • LPC54628_NXP is your custom target name that you can give for your porting like <hw_target_sdk>.
    • device is the name that you would give to your target board, as you may require board-specific porting in Device Management Client. Here it is LPC54628 but it can be any <custom_target_hw_name>.
    • os is your target SDK name. Here it is NXP but you can give your custom target SDK name like <target_sdk_name>.
    • sdk is name of the folder <target_sdk_name> that you created under pal-platform/SDK/. Ensure that the name is exactly the folder name since the script creates build files based on this.
    • version info is optional and can contain useful information to identify which SDK version is ported with a given release of Device Management Client.
  6. To verify everything is fine, run in mbed-cloud-client-example root:

    python pal-platform/pal-platform.py deploy --target <your_defined_target_in_pal_platform_json> generate

    For MCUXpresso SDK, the command would be:

    python pal-platform/pal-platform.py deploy --target LPC54628_NXP generate

    Check if there are any errors. Once the script completes successfully, it creates a __<target> folder under the root folder of mbed-cloud-client-example.

    For Xpresso, it creates folder __LPC54628_NXP.

  7. To verify that CMake can pick up the build structure, go to folder mbed-cloud-client-example/__<target> and run

    cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=./../pal-platform/SDK/<target_sdk_name>/SDK_<target_sdk_folder>/<toolchain_path_along_with_toolchain_cmake

    For MCUXpresso SDK, the command would be:

    cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=./../pal-platform/SDK/MCUXpresso_LPC54628/SDK_MCUXpresso_LPC54628/tools/cmake_toolchain_files/armgcc.cmake

    This will not generate a complete working build because CMake linking of target SDK sources and actual porting implementation in Device Management Client are still missing. However, this will give you an idea of a basic CMake system infrastructure being in place. You can progressively build the porting structure.

  8. Create a <target_sdk_name>.cmake file (LPCXpresso54628.cmake) file under pal-platform/SDK/<target_sdk_name>/ and fill in this information which is mandatory for porting any target:

    set (OS_BRAND <target_sdk_name>)
    add_definitions(-D<__target_sdk_name__>)
    ######### Configure all Options here ##########
    option(PAL_USE_CMSIS "Include CMSIS in build" OFF)
    option(PAL_USE_NETWORKING "Allow networking" ON)
    option(PAL_BUILD_BOARD_BRINGUP_TESTS "Build Tests" ON)
    option(PAL_ENABLED "Enable PAL" ON)
    
    #updating the autogen.cmake variables
    set (PAL_TARGET_DEVICE "<target_hw_name>")
    set (MBED_CLOUD_CLIENT_DEVICE <target_hw_name>)
    set (TLS_LIBRARY <target_tls_library_name>)
    set (NETWORK_STACK <target_network_library_name>)
    
    #If your target SDK has mbedtls then compile without its apps and tests
    SET(ENABLE_PROGRAMS OFF CACHE STRING "Avoid compiling mbedtls programs" )
    SET(ENABLE_TESTING OFF CACHE STRING "Avoid compiling mbedtls tests" )
    SET(ENABLE_PROGRAMS OFF)
    SET(ENABLE_TESTING OFF)
    

    For Xpresso SDK for LPC54628 the file would have:

    set (OS_BRAND NXP)
    add_definitions(-D__NXP__)
    ######### Configure all Options here ##########
    option(PAL_USE_CMSIS "Include CMSIS in build" OFF)
    option(PAL_USE_NETWORKING "Allow networking" ON)
    option(PAL_BUILD_BOARD_BRINGUP_TESTS "Build Tests" ON)
    option(PAL_ENABLED "Enable PAL" ON)
    
    #updating the autogen.cmake variables
    set (PAL_TARGET_OS "amazon-freertos")
    set (PAL_TARGET_DEVICE "LPC54628")
    set (CPU "cortex-m4")
    
    set (TLS_LIBRARY mbedTLS)
    set (NETWORK_STACK LWIP)
    
    #If your target SDK has mbedtls then compile without its apps and tests
    SET(ENABLE_PROGRAMS OFF CACHE STRING "Avoid compiling mbedtls programs" )
    SET(ENABLE_TESTING OFF CACHE STRING "Avoid compiling mbedtls tests" )
    SET(ENABLE_PROGRAMS OFF)
    SET(ENABLE_TESTING OFF)
    
  9. Add the toolchain flags for the CMake build. There is a template for the flags used by Device Management Client under pal-platform/Toolchain/<Toolchain>.

    If you are building for GCC ARM cross-embedded toolchain, copy the toolchain flag file ARMGCC-flags.cmake from pal-platform/Toolchain/ARMGCC to pal-platform/SDK/<target_sdk_name> at the same level as your CMakeLists.txt file.

    For MCUXpresso SDK, there is ARMGCC-flags.cmake under pal-platform/SDK/MCUXpresso_LPC54628.

Build your porting layer

To build the porting layer:

  1. Create porting source files structure under mbed-cloud-client-example/mbed-cloud-client/mbed-client-pal/Source/Port/Reference_Impl/OS_Specific/<OS_BRAND>.

    <OS_BRAND> is the value you defined in your pal-platform/SDK/<target_sdk_name>/CMakeLists.txt.

  2. For basic porting, create following folders and files and provide empty implementation for the files:

    mbed-client-pal
    |__Source
       |__Port
          |__Reference_Impl
             |__OS_Specific
                |__<OS_BRAND>
                   |__RTOS
                   |  |__pal_plat_rtos.c (Start with empty implementation for APIs defined under mbed-client-pal/Source/Port/Platform-API/pal-plat-rtos.h)
                   |__Networking
                   |   |__<NETWORK_STACK>
                   |      |__pal_plat_network.c (Start with empty implementation for APIs defined under mbed-client-pal/Source/Port/Platform-API/pal-plat-network.h)
                   |Board_Specific
                      |__Target_<MBED_CLOUD_CLIENT_DEVICE>
                         |__pal_plat_<MBED_CLOUD_CLIENT_DEVICE>.c (Start with empty implementation for board APIs defined under mbed-client-pal/Source/Port/Platform-API/pal-plat-rtos.h)
    
  3. Copy a complete target folder structure from other target SDK like NXP and then port your way back.

    If your target SDK is FreeRTOS and lwIP based then you don't need to modify any code since these are common components and have same code base.

    If there are differences in the API signature because of different versions of SDKs, you can resolve them easily, when you start building and verifying porting tests for your target SDK.

  4. Prepare the Device Management Client configuration files that enable the feature set applicable to your target SDK porting. Device Management Client comes with various feature sets but it is always good to start with step-by-step porting:

    1. Enable Device Management Client to compile, run and connect to Device Management.
    2. Add secure storage capability to store and retrieve Device Management Client credentials to presist over device resets.
    3. Add FOTA feature by adapting Device Management Client to your target SDK's bootloader functionality.

    To achieve the first of these steps, select appropriate configuration to your target SDK porting:

    TRNG Internal flash Configuration template
    Yes Yes define_trng_flash.txt
    No Yes define_no_trng_flash.txt
    Yes No define_trng_no_flash.txt
    No No define_no_trng_no_flash.txt

    In all template configurations, Device Management Client is built with a non-persistent storage component. This means your device will not store credentials in any persistent storage but in RAM while your application is running. The PAL_SIMULATOR_FILE_SYSTEM_OVER_RAM feature flag is turned ON by default in these configurations. This enables quick application compiling and running without the need for porting the storage first.

  5. Populate the PLATFORM_LIBS in your pal-platform/SDK/<target_sdk_name>/CMakeLists.txt by adding target SDK's platform native library Device Management Client requires to run mainly RTOS, lwIP, Mbed TLS and board-specific sources. Device Management Client requires this to link plaform porting against target SDK build.

    Here is an example from MCUXpresso SDK on how to add FreeRTOS, lwIP and Mbed TLS dependencies:

    add_library(PLATFORM_LIBS STATIC ${FreeRTOS_SRCS} ${LWIP_PORT_SRCS} ${BOARD_SOURCES} ${MBEDCRYPTO_SOURCES} ${MBEDTLS_SOURCES} ${MBEDX509_SOURCES} ${KSDK_SOURCES} ${MMCAU_SOURCES})
    add_dependencies(PLATFORM_LIBS lwipcore kvstore_flash_impl _mmcau)
    target_link_libraries(PLATFORM_LIBS lwipcore kvstore_flash_impl _mmcau)
    

    Now, your target platform porting build system with Device Management Client is ready for actual implementation.

  6. Go to folder mbed-cloud-client-example/__<target> and run:

    cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=./../pal-platform/SDK/<target_sdk_name>/<target_sdk_folder>/<toolchain_path_along_with_toolchain_cmake.

    For MCUXpresso SDK the command would be:

    cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=./../pal-platform/SDK/MCUXpresso_LPC54628/SDK_MCUXpresso_54628/tools/cmake_toolchain_files/armgcc.cmake

    There shouldn't be any CMake errors at the end of this step. If there are errors, resolve them by looking into previous steps to identify which of your added files require fixes. Fix the issue and run the command again until you you have a successful CMake build.

    Once, your CMake build succeed, run the make command. Resolve any compilation and linker issues until you have a clean build. The corresponding binaries are created under Debug or Release folder.

    A successful build should create following binaries:

    mbedCloudClientExample.bin
    NetworkTests.bin
    palTests.bin
    ROTTests.bin
    RTOSTests.bin
    sanityTests.bin
    SotpTests.bin
    SSTTests.bin
    TimeTests.bin
    TLSTests.bin
    UpdateTests.bin
    

    The important binaries for verifying your porting and Device Management Client are:

    • RTOSTests.bin to verify that your porting implementation in pal_plat_rtos.c is done correctly.
    • NetworkTests.bin to verify that your porting implementation in pal_plat_network.c is done correctly.
    • mbedCloudClientExample.bin to verify that your overall porting implementation is working and your application can now connect to Device Management.

Implement porting layers

To run Device Management Client application on target SDK you need to implement the porting layers.

In this phase, port RTOS and Network layer to get your Device Management Client application connecting to Device Management.

Most of the embedded targed SDK's are FreeRTOS-based, have lwIP as their preferred networking stack and have Mbed TLS as SSL and crypto component.

If your SDK has these components, follow the instructions for building your porting layer.

However, if your SDK has some other RTOS or lwIP or SSL library then you will have to complete your porting implementation yourself. The details for porting the different components are explained in:

While implementing, please pay extra attention to error propogation to above service layers through PAL errors so that Device Management Client can handle those errors and recover correctly.

Note: The pal_errors.h file should not be included directly. It will be included when you include pal.h.

The PAL errors file pal_errors.h lists all the different error codes that you might encounter when calling PAL functions. The errors are divided into modules that match the PAL modules, and all the error values are negative.

In your target porting code, make sure that the Platform API layer translates errors into the proper PAL error. When an error is returned by an implementation of the PAL Platform API, please make sure to map it to the appropriate PAL error code based on the cause of the error, and return the mapped error.

The reference ports for Mbed OS and Linux can serve as a guide for translating the error codes.

For more information, see the pal_errors.h file.

Testing ported components

To run the Device Management Client example application and successfully use Device Management Client over your target SDK, test the components individually.

Each device require a board or platform bring up code at application level. This is called Board Specific Porting (BSP) setup. This is unique to each target SDK and can also be hardware or network-configuration-specific as well.

To run your ported Device Management Client on a given target hardware, you need to provide an implementation for BSP.

The functionality Device Management Client requires to run the tests and application on a piece of hardware are defined in this include header

This is target-dependent code and should have its implementation under:

mbed-cloud-client-example
|__source
   |__platform
      |__<OS_BRAND> (is the value that you defined in your `pal-platform/SDK/<target_sdk_name>/CMakeLists.txt`)
         |__mcc_common_setup.c (Provide implementation for functions defined in mcc_common_setup.h placed under include folder)

For reference, check how those functions are defined for MCUXpresso SDK implementation under NXP folder. If your target SDK also has freeRTOS and lwIP as components, you can copy the implementation as-is and resolve any compile issues that you would have if those didn't match exactly.

When you have completed the implementation, you need to test your port. You may find it easier to test after implementing each module, rather than all at once.

If your ported components pass the following two tests, you can already try to run mbedCloudClientExample.bin and see if your device connects successfully to Device Management:

  • RTOSTests.bin to verify that your porting implementation in pal_plat_rtos.c is done correctly.
  • NetworkTests.bin to verify that your porting implementation in pal_plat_network.c is done correctly.