If you built an application based on nRF5 SDK v14.2.0, complete the actions listed in the following sections to migrate your application to nRF5 SDK v15.0.0.
Note that this migration guide does not list all changes, but it covers the most important changes that require you to update your code. See the release notes for further information on changes that were made in this release.
When initializing the advertising module (ble_adv_modes_config_t), a different bandwidth can be selected for the primary and secondary PHY (
ble_adv_secondary_phy). Accepted values are (BLE_GAP_PHY_1MBPS, BLE_GAP_PHY_2MBPS, and BLE_GAP_PHY_CODED). The
ble_adv_extended_enabled parameter must be set to true if your application is to use extended advertising.
Action: Make sure
ble_adv_extended_enabled = false; to preserve advertising functionality similar to older SDKs.
BLE_ADV_MODE_DIRECTED has been renamed to BLE_ADV_MODE_DIRECTED_HIGH_DUTY.
BLE_ADV_MODE_DIRECTED_SLOW renamed to BLE_ADV_MODE_DIRECTED.
Action: When initializing or handling events from the Advertising module, make sure you are referring to the correct directed mode.
ble_advdata_set() has been deprecated. The reason is because
sd_ble_gap_adv_data_set() has been removed from the SoftDevice API. Instead, you can use
ble_advdata_encode() before calling the SoftDevice function
You may need to call
ble_advdata_encode() twice, because
ble_advdata_set() might have both advertising data and scan response data as input. The function
ble_advdata_encode() only encodes one at a time.
For some examples, we have moved the setting of advertising parameters so they are set together with advertising data.
Affects the following BLE service modules:
Declaring service instance with a modified macro
This affects ble_hids, ble_nus, and ble_ias modules.
Action: Add missing parameters to the macro.
Initializing service instance
This affects only the ble_hids module.
Action: Declare initialization structures for Input/Output/Feature Reports as static.
Additional parameter required
Some functions from the service module API require an additional parameter - connection handle. This affects ble_hids, ble_nus, and ble_bas modules.
Action: Pass an additional parameter (connection handle) when calling service module API functions.
ble_conn_state has gained a dependency on nrf_atflags (
PM_LINK_SECURED_PROCEDURE_ has been renamed to
Note the new dependecy in ble_conn_state.
All interfaces to the Secure DFU Bootloaders over the DFU protocol and through Supervisor Calls or flash pages are backwards compatible with previous versions of the Secure DFU.
Note that the value 0 as the first element in the sd-req array in the init packet has gained a special meaning in this version of the DFU, because of the support for SoftDevice independent updates. Additionally, the SV Calls to set name and bonding data have gained a new error return code for when the data cannot be written because of write protection.
Some of the files used by the bootloader and DFU have changed names. For example,
dfu_public_key.c is now located in
examples/dfu folder, while
dfu_req_handling.c has been renamed to
nrf_dfu_req_handler.c and moved to
components/libraries/bootloader/dfu. See bootloader example projects for details.
The bootloaders are no longer dependent on the SoftDevice to be present, unless the transport (only BLE for now) requires it. This has brought some changes to the meaning of some compiler definitions.
SOFTDEVICE_PRESENT is no longer in use in the bootloader code, as this can no longer be known at compile time.
BLE_STACK_SUPPORT_REQD is used in the bootloader code to specify whether the SoftDevice is required for DFU operation.
Old configuration parameters with file names in parentheses existed only as #defines in that file.
|Old config name||New config name|
|(new config)||NRF_DFU_BLE_BUFFERS_OVERRIDE (only for BLE transport)|
|(new config)||NRF_DFU_BLE_BUFFERS (only for BLE transport)|
|(new config)||NRF_DFU_SERIAL_USB_RX_BUFFERS (only for USB transport)|
|(new config)||NRF_DFU_SERIAL_UART_USES_HWFC (only for UART transport)|
|(new config)||NRF_DFU_SERIAL_UART_RX_BUFFERS (only for UART transport)|
For sane defaults and documentation for new configuration parameters, see the
sdk_config.h file in SDK v15.0.0 bootloader examples.
Previously, all secure bootloader examples used the µECC library for implementation of cryptographic routines. The examples for nRF52832 still use µECC, but nrf_crypto now also supports other software backends, like a library written for Nordic Semiconductor by Oberon (nrf_oberon). Size limitations have prevented the examples from being ported, but if you are willing to take a possible size hit, the backend can be changed (see below). The examples for nRF52840 now all use the CryptoCell hardware present on that chip, instead of µECC.
For more information about changes to nrf_crypto, see Crypto.
sdk_config.h, set the following defines:
If you are using the API in
nrf_dfu.h directly, i.e. not using the provided
nrf_bootloader.c files, you will find that a few things have changed.
The bootloader code has been restructured, and some functionality has been moved from the DFU to the bootloader.
The DFU has started sending events (
nrf_dfu_types.h) to allow the user to take action.
nrf_bootloader_dfu_timers.h). The timer is reset on receiving the event NRF_DFU_EVT_OBJECT_RECEIVED.
dfu_observer() inthe main file of a bootloader example for details.
nrf_dfu_button_enter_check()have been moved to
This function has been stripped of most functionality, and should now only be called when DFU is requested, i.e. after the enter checks.
The signature of nrf_dfu_init() has been changed to take an event observer (for
NRF_DFU_SCHED_EVENT_DATA_SIZE must now be considered when calculating the app_scheduler queue element size.
DFU requests are now handled asynchronously.
The result of a request and its response are no longer returned directly by nrf_dfu_req_handler_on_req(), instead they are returned via a callback to the function specified in
nrf_dfu_request::callback::response. The signature of nrf_dfu_req_handler_on_req() was modified to accomodate these changes. If you are not using the bootloader, then you should take care of initializing the scheduler before initializing nrf_dfu_req_handler.
If you do not use either the bootloader or nrf_dfu, then you should handle the new DFU events (
nrf_dfu_evt_type_t) received through the callback specified via the "observer" param in nrf_dfu_req_handler_init() to implement the desired behavior on DFU progress, start, completion etc.
The buffers used to store incoming firmware images were moved from
dfu_req_handling.c to the transports. The transports provide a pointer to these buffers to
nrf_dfu_req_handler.c as part of a write request (
nrf_dfu_request::write::p_data). When the buffer is written to flash, the
nrf_dfu_request::callback::write callback is invoked and the buffer can be freed by the transport.
The values of
nrf_dfu_req_op_t (now nrf_dfu_op_t) have been aligned to match the serialized opcode values used between the DFU host and the device. Note that this change does not break or affect backward compatibility.
Several datatypes have changed:
|Old type name||New type name||Comment|
|nrf_dfu_op_t||Fields have changed|
|nrf_dfu_request_t||Fields have changed|
|nrf_dfu_response_t||Fields have changed|
The driver no longer automatically acknowledges the IN direction setup transfer.
The shortcut set inside the driver when the last setup data IN transfer was prepared was removed. It means that now the higher layer must take care of calling nrf_drv_usbd_setup_clear for both directions of setup transfer.
Descriptor generation has been overhauled, and therefore class instance macros have been changed.
Action: Remove the old definition of
m_cdc_acm_class_descriptors and pass the values directly to the APP_USBD_CDC_ACM_GLOBAL_DEF macro. An additional parameter to specify the CDC protocol has been added.
m_hid_generic_class_descriptors definition. Replace them with APP_USBD_HID_GENERIC_SUBCLASS_REPORT_DESC macro and reports table. Pass parameters directly to the APP_USBD_HID_GENERIC_GLOBAL_DEF macro.
Action: Remove definitions of
m_hp_audio_class_descriptors. Create each descriptor using appropriate macro and pass the descriptors directly to the APP_USBD_AUDIO_GLOBAL_DEF macro. Last 4 new parameters are: streaming delay, format tag, endpoint size, and streaming type.
get_descriptors class method has been replaced with
feed_descriptors with different parameters.
feed_descriptors, adding a pointer to a buffer. Use a while loop to iterate through all descriptors. Before calling
feed_descriptors, the app_usbd_class_descriptor_ctx_t variable must be defined and initialized using APP_USBD_CLASS_DESCRIPTOR_INIT.
class_get_descriptors has different parameters and return value.
Action: Add a pointer to the descriptor (p_desc) to the function call.
app_usbd_cdc_acm_read now specifies the number of bytes to read. Use app_usbd_cdc_acm_read_any to retain previous usage.
app_usbd_cdc_acm_read with app_usbd_cdc_acm_read_any.
usbd_user_ev_handler is now also used for processing power events. Events are mapped as follows:
APP_USBD_PROCESS_POWER_EVENTS can be set to 0 to disable this feature.
Action: Add handling of aforementioned events in
usbd_user_ev_handler, for example:
Replace them with enabling power events after appending the last class:
Renamed the following parameters:
Action: Change old names to new ones.
setup_device_req_std_handler instead of
APP_USBD_CONFIG_MAX_POWER is now used in bMaxPower in configuration descriptor. Default value is 500.
Action: It might be necessary to define it.
Clock initialization has been removed from app_usbd_init().
Various ways of handling SOF have been implemented. To keep using the normal handling, APP_USBD_CONFIG_SOF_HANDLING_MODE must be set to "Normal queue".
nrf_crypto has gone through extensive changes from version 14.x. A lot of the new APIs that are added in nrf_crypto APIs in nRF5 SDK v15.0.0 are not mentioned in this migration guide. To get information about the new APIs, see the respective API documentation sections in the infocenter: Cryptography library.
This configuration has changed from SDK version 14.x.
The nrf_crypto frontend/backend system relies on configuration of
sdk_config.h. Multiple backends are supported and in some cases multiple backends can be used at the same time (to ensure that all required cryptographic routines are supported).
This configuration chapter assumes that an
sdk_config.h file containing all required configurations is present. If this requirement is not met, it might lead to compile warnings and/or errors. Copy a valid
sdk_config.h from any of the nrf_crypto examples to use as a starting point.
Enable nrf_crypto by setting the NRF_CRYPTO_ENABLED define to 1 in
Select one or more backends appropriate to your nRF device and use case, and enable by setting one or more defines in the following table to 1:
|NRF_CRYPTO_BACKEND_CC310_BL_ENABLED||nRF52840 only, hardware-accelerated for SDFU|
|NRF_CRYPTO_BACKEND_CC310_ENABLED||nRF52840 only, hardware accelerated|
|NRF_CRYPTO_BACKEND_CIFRA_ENABLED||For AES EAX|
|NRF_CRYPTO_BACKEND_MBEDTLS_ENABLED||mbed TLS, requires memory management|
|NRF_CRYPTO_BACKEND_MICRO_ECC_ENABLED||ECDH and ECDSA|
|NRF_CRYPTO_BACKEND_NRF_HW_RNG_ENABLED||RNG seed for nRF52832 and nRF52810 use cases|
|NRF_CRYPTO_BACKEND_NRF_SW_ENABLED||SHA-256 for SDFU use|
|NRF_CRYPTO_BACKEND_OBERON_ENABLED||ECDH, ECDSA, hash, HMAC, HKDF|
Note that multiple backends can be enabled at the same time, as long as the features supported by multiple backends are not duplicated. For details on configuring multiple backends, see Configuring nrf_crypto frontend and backends.
It is possible to optimize code and RAM size by disabling unused functionality. Do this by disabling unused AES modes, ECC curves etc. in the enabled backends in the
Initialization of nrf_crypto is similar to previous versions of the nrf_crypto API.
Calling nrf_crypto_init is required before nrf_crypto APIs can be used like for previous versions of the nRF5 SDKs. Initializing nrf_crypto:
There is a new range allocated to nrf_crypto related errors. The following is a detailed description of the common error codes shared by all nrf_crypto APIs. All nrf_crypto error codes use the same base
|NRF_ERROR_CRYPTO_NOT_INITIALIZED||0x8500||nrf_crypto_init was not called prior to this crypto function.|
|NRF_ERROR_CRYPTO_CONTEXT_NULL||0x8501||A null pointer was provided for the context structure.|
|NRF_ERROR_CRYPTO_CONTEXT_NOT_INITIALIZED||0x8502||The context was not initialized prior to this call or it was corrupted.|
|NRF_ERROR_CRYPTO_FEATURE_UNAVAILABLE||0x8503||The function was called with a feature that is unavailable.|
|NRF_ERROR_CRYPTO_BUSY||0x8504||The function could not be called because the crypto backend was busy.|
|NRF_ERROR_CRYPTO_INPUT_NULL||0x8510||One or more of the input arguments for this function were NULL.|
|NRF_ERROR_CRYPTO_INPUT_LENGTH||0x8511||The length of one or more of the input arguments was invalid.|
|NRF_ERROR_CRYPTO_INPUT_LOCATION||0x8512||Input data not in RAM.|
|NRF_ERROR_CRYPTO_OUTPUT_NULL||0x8513||One or more of the output arguments for this function were NULL.|
|NRF_ERROR_CRYPTO_OUTPUT_LENGTH||0x8514||The length of one or more output arguments was too small.|
|NRF_ERROR_CRYPTO_ALLOC_FAILED||0x8515||A required memory allocation failed.|
|NRF_ERROR_CRYPTO_INTERNAL||0x8516||An internal error occurred when calling this function.|
|NRF_ERROR_CRYPTO_INVALID_PARAM||0x8517||Invalid combination of input parameters.|
|NRF_ERROR_CRYPTO_KEY_SIZE||0x8518||Size of the key is not supported by the chosen backend.|
|NRF_ERROR_CRYPTO_STACK_OVERFLOW||0x8519||Stack overflow detected.|
Some of these error codes are only observed in nRF52840 devices when using the CC310 hardware accelerated cryptographic engine as backend to nrf_crypto:
The types used in input/output in nrf_crypto are different from the previous versions of nRF5 SDK.
Previously, versions of nrf_crypto used macro calls to allocate variables used in nrf_crypto operations. These macros have been removed and replaced by regular structure types like context structures and/or special types for holding key material and other input or output parameters.
Macros used to create variables (as value-length types) that are no longer valid in nrf_crypto:
|Macro to create a private key.|
|Macro to create a public key.|
|Macro to calculate the required size for a private key given type.|
|Macro to calculate the required size for a public key given type.|
|Macro to create a raw private key.|
|Macro to create a raw private key given buffer as input.|
|Macro to create a raw public key.|
|Macro to create a raw public key given buffer as input.|
|Macro to create a hash context structure as buffer.|
|Macro to create a hash digest and backing buffer.|
|Macro to create a hash digest given buffer as input.|
|Macro to create an ECDSA Sign context.|
|Macro to create an ECDSA Verify context.|
|Macro to create an ECDSA signature.|
|Macro to create an ECDSA signature given buffer as input.|
Since these macros are no longer valid, use the types in the following chapters.
New structure types for ECC operations (ECDH and ECDSA):
|nrf_crypto_ecdh_context_t||Context structure used for ECDH operation.|
|nrf_crypto_ecdsa_sign_context_t||Context structure used for ECDSA signing.|
|nrf_crypto_ecdsa_verify_context_t||Context structure used for ECDSA verification.|
|nrf_crypto_ecc_private_key_t||ECC Private key provided for ECDH calculation or ECDSA signing.|
|nrf_crypto_ecc_public_key_t||ECC Public key provided for ECDH calculation or ECDSA verification.|
|nrf_crypto_ecdsa_signature_t||ECDSA signature (all types).|
Note that the content of the context structure is dependent on a parameter given during the API calls and the enabled backend. These types should be seen as opaque types.
New structure types for hash operations
|nrf_crypto_hash_context_t||Context structure used for hash calculation.|
|nrf_crypto_hash_sha256_digest_t||Hash digest structure.|
Note that the content of the context structure is dependent on the parameter given during the API calls and the enabled backend. These types should be seen as opaque types.
Structure types used for context information and input and output parameters are structurally provided as unions, where the nrf_crypto frontend APIs accepts input/output types sized to the largest requirements in the configured backends and in specific modes, ECC curve types etc. The size of the context structures may differ quite a lot dependent on what backend is used and what features are enabled in the backends. See the Sizes of the types defined by nrf_crypto for details on the structure sizes used in nrf_crypto APIs.
nrf_crypto in nRF5 SDK v14.x had APIs which took value length structures for inputs. This is no longer the case in nRF5 SDK v15.0.0.
Some input/output parameters are given in pairs consisting of a pointer to a buffer and a length specifier. If the output does not use the whole allocated buffer, some APIs will update the length specifier to reflect the actual size of the result.
The following is an example of a function call that uses length specifiers in API calls:
Note that the digest_size is taken in as a pointer to a size_t type. digest_size will be updated to reflect that a SHA-256 digest has been calculated when this API is called, regardless if the hash_digest size provided in the API call is larger.
nrf_crypto APIs support automatic memory allocation (optional). This is different from nRF5 SDK version 14.x nrf_crypto APIs.
Some APIs will allow sending in a NULL pointer as an argument, in which case NRF_CRYPTO_ALLOC will be used to allocate memory for variables used during the nrf_crypto operation. See the API documentation for the Cryptography library frontends for information on memory requirements for the the input/output variables.
A common use case for sending NULL as an input parameter is for context structures used in calculations, like in the following example:
It is recommended to use static variables for parameters used in the nrf_crypto calls if this is a possibility. This ensures that there will be denial of service while trying to execute nrf_crypto API calls due to limitations in shared resources.
This is a new feature compared to nRF5 SDK version 14.x.
By default, nrf_crypto is configured to use stack allocation through functionality available in alloca for dynamic memory allocation. This memory is normally allocated on the stack at the beginning of a function call and freed at the end. It is not possible to use stack allocation for variables that are intended to have extended lifetime outside of the API call. If this is a requirement, use the
C dynamic memory or nRF5 SDK Memory Manager in this case.
To control the memory management, edit
NRF_CRYPTO_ALLOCATOR in sdk_config to a number from 0 to 4 according to the following table:
|Default configuration||0||Uses stack allocation (alloca), except IAR which uses nRF5 SDK Memory Manager.|
|User macros||1||User-provided macros for NRF_CRYPTO_ALLOC and NRF_CRYPTO_FREE.|
|Stack allocation (Alloca)||2||Uses stack allocation, not usable for IAR projects!|
|C dynamic memory||3||Heap based allocation (using malloc).|
|nRF5 SDK Memory Manager||4||Dynamic memory allocation. Requires extra configuration.|
Note that the nRF5 SDK Memory Manager (mem_manager) requires additional configuration parameters in
sdk_config.h and a call to initialize it by running prior to using the nrf_crypto APIs. The correct configuration for using the nRF5 SDK Memory Manager is outside of the scope of this guide. For details about the nRF5 SDK Memory Manager module, see Memory Manager. For specific information on the required sizes of buffers in mem_manager for ECC, ECDSA, and ECDH use cases, see Memory management in mbed TLS.
If mbed TLS is configured to be the nrf_crypto backend, there might be some requirements to configure memory management. This is because mbed TLS APIs rely on dynamic memory management for some of the APIs. Information about which APIs require dynamic memory allocation is outside of the scope of this migration guide. Refer to mbed TLS documentation for details on memory requirements.
The C runtime library in IAR (version 7.x and 8.x) does not provide the alloca functionality. This means that stack allocated memory management is not available for nrf_crypto APIs. Therefore, backends that require dynamic memory management must be configured to either use C dynamic memory or Memory Manager.
Previous versions of nrf_crypto were assumed input data to be little-endian or big-endian based on the configuration parameters in the APIs. This option is removed from nrf_crypto in SDK v15.0.0.
All nrf_crypto APIs now assume big-endian input/output to reflect the cryptographic algorithm standards.
Note that BLE standard assumes data for LESC to be in little-endian format. The same is the case for the Nordic proprietary Secure DFU and the PC tool used to generate FW upgrade packets (nrfutil). The micro-ecc runtime library compiled through nRF5 SDKs is using little-endian.
The Nordic proprietary Secure DFU assumes little-endian types (public key, signature, and hash digest). To conform to this, there are some added
sdk_config.h parameters to make the nrf_crypto APIs support little-endian input/output.
sdk_config.hparameters are only provided as a convenience to porting from existing solutions and to keep the code size down in Secure DFU.
Configuration parameters to enable little-endian support in SDFU use- cases:
|NRF_CRYPTO_BACKEND_MICRO_ECC_LITTLE_ENDIAN_ENABLED||For SDFU+nRF52832: Enable this to use nrf_crypto_ecdsa_verify with little-endian keys, hash, and signature input.|
|NRF_CRYPTO_BACKEND_NRF_SW_HASH_LITTLE_ENDIAN_DIGEST_ENABLED||For SDFU+nRF52832: Enable this to use nrf_crypto_hash with little-endian digest.|
|NRF_CRYPTO_BACKEND_CC310_BL_HASH_LITTLE_ENDIAN_DIGEST_ENABLED||For SDFU+nRF52840: Enable this to use nrf_crypto_hash with little-endian digest.|
|NRF_CRYPTO_BACKEND_CC310_BL_ECC_LITTLE_ENDIAN_ENABLED||For SDFU+nRF52840: Enable this to use nrf_crypto_ecdsa_verify with little-endian keys, hash, and signature input.|
Note that these changes will only be available for the micro-ecc and nrf_cc310_bl backends. This is solely for use with Secure DFU. If little-endian input/output is required outside of this, use any of the conversion functions mentioned in the following section.
There are some convenience functions that can be used to change endianness of input and output parameters like ECC public/private keys, ECDSA signatures, ECDH shared secrets, and hash digests.
The functions are available by adding the following include
#include "nrf_crypto_shared.h", and calling the following APIs:
|Swap byte order in buffer with copy.||Swap hash digest, private keys, and ECDH shared secret.|
|Swap byte order in buffer in-place.||Swap hash digest, private keys, and ECDH shared secret.|
|Swap byte order for pairs with copy.||Public keys [X,Y], Signatures [R,S].|
|Swap byte order for pairs in-place.||Public keys [X,Y], Signatures [R,S].|
Note that ECC Public keys and ECDSA signatures are buffers that contain two parts. Both parts must be swapped individually. For an ECC public key which is a point [X,Y], both X and Y must be swapped individually. For a ECDSA signature [R, S], both R and S must be swapped individually.
nrf_crypto APIs have changed since SDK version v14.x. Key to the changes is the use of info structures to select the mode of operation.
Every example assumes that nrf_crypto is included with
#include "nrf_crypto.h" and that the correct backend has been configured according to the migration guide.
The following code shows how to calculate hash.
The following code shows how to calculate a shared secret.
The following code shows how to verify an ECDSA signature.
Almost all hardware drivers were moved to a new module called "nrfx" that is also available as a separate entity at the following location: https://github.com/NordicSemiconductor/nrfx. In SDK v15.0.0, the "nrfx" module is located in the "modules/nrfx" folder.
Because of this change, the drivers API has been moved to a new consistent namespace that uses prefixes "nrfx_" for functions and type names, and "NRFX_" for macros and enumeration values. To provide compatibility with existing applications based on nRF5 SDK v14.2.0, a special legacy layer is provided. It is located in the "integration/nrfx/legacy" folder and it performs required translation of the former drivers API and configuration settings to their new implementations.
For new applications, it is strongly recommended to use the new API directly, since the legacy layer will be deprecated and eventually removed in future SDK releases. For existing applications the migration to the new API in most cases will be quite simple and require only:
There are a few exceptions though:
statusparameter. After the driver finishes using the buffers, it passes them back to the application via the
p_releasedparameter of the data handler. See nrfx_i2s documentation for detailed information.
Inline functions from
nrf_atomic.h are moved to
nrf_atomic.c which must now be included in the project.
Instances of the objects are now created in a custom memory section. For Segger Embedded Studio and ARM GCC, linker files must define these sections (see provided generic linker scripts).
echo are now called:
cli colors, and
cli echo respectively.
nrf_spi_mngr_perform() has a new parameter (p_config) with SPI configuration. If
p_config is NULL, the default configuration is used.
nrf_twi_mngr_perform() has a new parameter (p_config) with TWI configuration. If
p_config is NULL, the default configuration is used.
Enabling dynamic changes of the TX_POWER and MAX_TX_ATTEMPTS in Gazell stack is followed by changes in the Gazell API.
For the TX_POWER, function API has not been changed, but from now on there is no need to disable Gazell stack before changing this parameter. The nrf_gzll_set_tx_power function will not set NRF_GZLL_ERROR_CODE_ATTEMPTED_TO_CONFIGURE_WHEN_ENABLED error as it has done in previous stack versions.
For the TX_ATTEMPTS_NUM, function API has been changed and does not return Boolean result, as it will always succeed.