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:
- Adapt the target SDK to existing client build system and port RTOS and lwIP component for Device Management Client while running storage over RAM.
- 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.
- 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:
- Get a new SDK.
- 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:
- Implement porting layers to run the Device Management Client application on the target SDK.
- Test ported components individually.
- 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:
-
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. -
Clone the Device Management Client example:
git clone https://github.com/PelionIoT/mbed-cloud-client-example.git
-
Go to
mbed-cloud-client-example/pal-platform
folder and create a new folder<target_sdk_name>
underSDK
.In the example, it is
LPCXpresso54628
. -
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
. -
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 hereAn 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 isLPC54628
but it can be any<custom_target_hw_name>
.os
is your target SDK name. Here it isNXP
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 underpal-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.
-
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 ofmbed-cloud-client-example
.For Xpresso, it creates folder
__LPC54628_NXP
. -
To verify that CMake can pick up the build structure, go to folder
mbed-cloud-client-example/__<target>
and runcmake -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.
-
Create a
<target_sdk_name>.cmake
file (LPCXpresso54628.cmake
) file underpal-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)
-
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
frompal-platform/Toolchain/ARMGCC
topal-platform/SDK/<target_sdk_name>
at the same level as yourCMakeLists.txt
file.For MCUXpresso SDK, there is
ARMGCC-flags.cmake
underpal-platform/SDK/MCUXpresso_LPC54628
.
Build your porting layer
To build the porting layer:
-
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 yourpal-platform/SDK/<target_sdk_name>/CMakeLists.txt
. -
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)
-
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.
-
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:
- Enable Device Management Client to compile, run and connect to Device Management.
- Add secure storage capability to store and retrieve Device Management Client credentials to presist over device resets.
- 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 turnedON
by default in these configurations. This enables quick application compiling and running without the need for porting the storage first. -
Populate the
PLATFORM_LIBS
in yourpal-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.
-
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 underDebug
orRelease
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 inpal_plat_rtos.c
is done correctly.NetworkTests.bin
to verify that your porting implementation inpal_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 inpal_plat_rtos.c
is done correctly.NetworkTests.bin
to verify that your porting implementation inpal_plat_network.c
is done correctly.