Bringing in Softdevice but excluding BLE feature and improvements in feature defines

pull/10652/head
RFulchiero 2018-07-09 13:57:57 -05:00 committed by desmond.chen
parent 511f8ebbd7
commit cd5b451320
24 changed files with 6431 additions and 5 deletions

View File

@ -0,0 +1,87 @@
/**
* Copyright (c) 2012 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ble_radio_notification.h"
#include <stdlib.h>
static bool m_radio_active = false; /**< Current radio state. */
static ble_radio_notification_evt_handler_t m_evt_handler = NULL; /**< Application event handler for handling Radio Notification events. */
void SWI1_IRQHandler(void)
{
m_radio_active = !m_radio_active;
if (m_evt_handler != NULL)
{
m_evt_handler(m_radio_active);
}
}
uint32_t ble_radio_notification_init(uint32_t irq_priority,
uint8_t distance,
ble_radio_notification_evt_handler_t evt_handler)
{
uint32_t err_code;
m_evt_handler = evt_handler;
// Initialize Radio Notification software interrupt
err_code = sd_nvic_ClearPendingIRQ(SWI1_IRQn);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
err_code = sd_nvic_SetPriority(SWI1_IRQn, irq_priority);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
err_code = sd_nvic_EnableIRQ(SWI1_IRQn);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
// Configure the event
return sd_radio_notification_cfg_set(NRF_RADIO_NOTIFICATION_TYPE_INT_ON_BOTH, distance);
}

View File

@ -0,0 +1,82 @@
/**
* Copyright (c) 2012 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** @file
*
* @defgroup ble_radio_notification Radio Notification Event Handler
* @{
* @ingroup ble_sdk_lib
* @brief Module for propagating Radio Notification events to the application.
*/
#ifndef BLE_RADIO_NOTIFICATION_H__
#define BLE_RADIO_NOTIFICATION_H__
#include <stdint.h>
#include <stdbool.h>
#include "nrf_soc.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@brief Application radio notification event handler type. */
typedef void (*ble_radio_notification_evt_handler_t) (bool radio_active);
/**@brief Function for initializing the Radio Notification module.
*
* @param[in] irq_priority Interrupt priority for the Radio Notification interrupt handler.
* @param[in] distance The time from an Active event until the radio is activated.
* @param[in] evt_handler Handler to be executed when a radio notification event has been
* received.
*
* @return NRF_SUCCESS on successful initialization, otherwise an error code.
*/
uint32_t ble_radio_notification_init(uint32_t irq_priority,
uint8_t distance,
ble_radio_notification_evt_handler_t evt_handler);
#ifdef __cplusplus
}
#endif
#endif // BLE_RADIO_NOTIFICATION_H__
/** @} */

View File

@ -0,0 +1,109 @@
/**
* Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "nrf_dfu_mbr.h"
#include "nrf_mbr.h"
#include "nrf_dfu_types.h"
#include "nrf_log.h"
#include "nrf_bootloader_info.h"
#define MBR_IRQ_FORWARD_ADDRESS_ADDRESS (0x20000000) //!< The address of the variable that decides where the MBR forwards interrupts
uint32_t nrf_dfu_mbr_copy_bl(uint32_t * p_src, uint32_t len)
{
uint32_t ret_val;
uint32_t const len_words = len / sizeof(uint32_t);
sd_mbr_command_t command =
{
.command = SD_MBR_COMMAND_COPY_BL,
.params.copy_bl.bl_src = p_src,
.params.copy_bl.bl_len = len_words
};
ret_val = sd_mbr_command(&command);
return ret_val;
}
uint32_t nrf_dfu_mbr_init_sd(void)
{
uint32_t ret_val;
sd_mbr_command_t command =
{
.command = SD_MBR_COMMAND_INIT_SD
};
ret_val = sd_mbr_command(&command);
return ret_val;
}
uint32_t nrf_dfu_mbr_irq_forward_address_set(void)
{
uint32_t ret_val = NRF_ERROR_INVALID_PARAM;
uint32_t address = MBR_SIZE;
NRF_LOG_DEBUG("running irq table set");
#ifndef BLE_STACK_SUPPORT_REQD
sd_mbr_command_t command =
{
.command = SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET,
.params.irq_forward_address_set.address = address,
};
ret_val = sd_mbr_command(&command);
#endif
if (ret_val == NRF_ERROR_INVALID_PARAM)
{
// Manually set the forward address if this MBR doesn't have the command.
*(uint32_t *)(MBR_IRQ_FORWARD_ADDRESS_ADDRESS) = address;
ret_val = NRF_SUCCESS;
}
NRF_LOG_DEBUG("After running irq table set");
return ret_val;
}

View File

@ -0,0 +1,90 @@
/**
* Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**@file
*
* @defgroup sdk_nrf_dfu_mbr MBR functions
* @{
* @ingroup nrf_dfu
*/
#ifndef NRF_DFU_MBR_H__
#define NRF_DFU_MBR_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Function for copying the bootloader using an MBR command.
*
* @param[in] p_src Source address of the bootloader data to copy.
* @param[in] len Length of the data to copy in bytes.
*
* @return This function will return only if the command request could not be run.
* See @ref sd_mbr_command_copy_bl_t for possible return values.
*/
uint32_t nrf_dfu_mbr_copy_bl(uint32_t * p_src, uint32_t len);
/** @brief Function for initializing the SoftDevice using an MBR command.
*
* @retval NRF_SUCCESS If the SoftDevice was initialized successfully.
* Any other return value indicates that the SoftDevice
* could not be initialized.
*/
uint32_t nrf_dfu_mbr_init_sd(void);
/** @brief Function for setting the address of the IRQ table to the app's using an MBR command.
*
* @retval NRF_SUCCESS If the address of the new irq table was set. Any other
* return value indicates that the address could not be set.
*/
uint32_t nrf_dfu_mbr_irq_forward_address_set(void);
#ifdef __cplusplus
}
#endif
#endif // NRF_DFU_MBR_H__
/** @} */

View File

@ -0,0 +1,302 @@
/**
* Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**@file
*
* @defgroup sdk_nrf_dfu_types DFU types
* @{
* @ingroup nrf_dfu
*/
#ifndef NRF_DFU_TYPES_H__
#define NRF_DFU_TYPES_H__
#include <stdint.h>
#include <stddef.h>
#include "nrf.h"
#include "nrf_mbr.h"
#include "app_util_platform.h"
#include "sdk_config.h"
#if defined(NRF_DFU_TRANSPORT_BLE) && NRF_DFU_TRANSPORT_BLE
#include "ble_gap.h"
#define SYSTEM_SERVICE_ATT_SIZE 8 /**< Size of the system service attribute length including CRC-16 at the end. */
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define INIT_COMMAND_MAX_SIZE 256 /**< Maximum size of the init command stored in dfu_settings. */
/** @brief Size of a flash page. This value is used for calculating the size of the reserved
* flash space in the bootloader region.
*/
#if defined(NRF51)
#define CODE_PAGE_SIZE (PAGE_SIZE_IN_WORDS * sizeof(uint32_t))
#elif defined(NRF52) || defined(NRF52840_XXAA)
#define CODE_PAGE_SIZE (MBR_PAGE_SIZE_IN_WORDS * sizeof(uint32_t))
#else
#error "Architecture not set."
#endif
/** @brief Maximum size of a data object.*/
#if defined(NRF51)
#define DATA_OBJECT_MAX_SIZE (CODE_PAGE_SIZE * 4)
#elif defined(NRF52_SERIES) || defined (__SDK_DOXYGEN__)
#define DATA_OBJECT_MAX_SIZE (CODE_PAGE_SIZE)
#else
#error "Architecture not set."
#endif
/** @brief Page location of the bootloader settings address.
*/
#if defined (NRF51)
#define BOOTLOADER_SETTINGS_ADDRESS (0x0003FC00UL)
#elif defined( NRF52810_XXAA )
#define BOOTLOADER_SETTINGS_ADDRESS (0x0002F000UL)
#elif defined( NRF52832_XXAA )
#define BOOTLOADER_SETTINGS_ADDRESS (0x0007F000UL)
#elif defined(NRF52840_XXAA)
#define BOOTLOADER_SETTINGS_ADDRESS (0x000FF000UL)
#else
#error No valid target set for BOOTLOADER_SETTINGS_ADDRESS.
#endif
#define BOOTLOADER_SETTINGS_PAGE_SIZE (CODE_PAGE_SIZE)
/**
* @brief MBR parameters page in UICR.
*
* Register location in UICR where the page address of the MBR parameters page is stored (only used by the nRF52 MBR).
*
* @note If the value at the given location is 0xFFFFFFFF, no MBR parameters page is set.
*/
#define NRF_UICR_MBR_PARAMS_PAGE_ADDRESS (NRF_UICR_BASE + 0x18)
#define NRF_MBR_PARAMS_PAGE_SIZE (CODE_PAGE_SIZE)
/** @brief Page location of the MBR parameters page address.
*/
#if defined(NRF52840_XXAA) || defined(NRF52840_XXAA_ENGA)
#define NRF_MBR_PARAMS_PAGE_ADDRESS (0x000FE000UL)
#elif defined(NRF52832_XXAA)
#define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0007E000UL)
#elif defined(NRF52810_XXAA)
#define NRF_MBR_PARAMS_PAGE_ADDRESS (0x0002E000UL)
#endif
/** @brief Size (in bytes) of the flash area reserved for application data.
*
* The area is found at the end of the application area, next to the start of
* the bootloader. This area will not be erased by the bootloader during a
* firmware upgrade. The default value is 3 pages which matches the size used
* in most SDK examples.
*/
#ifndef DFU_APP_DATA_RESERVED
#define DFU_APP_DATA_RESERVED (CODE_PAGE_SIZE * 3)
#endif
/** @brief Total size of the region between the SoftDevice and the bootloader.
*/
#define DFU_REGION_END(bootloader_start_addr) ((bootloader_start_addr) - (DFU_APP_DATA_RESERVED))
#ifdef BLE_STACK_SUPPORT_REQD
#define DFU_REGION_START (nrf_dfu_bank0_start_addr())
#else
#define DFU_REGION_START (MBR_SIZE)
#endif
#define DFU_REGION_TOTAL_SIZE ((DFU_REGION_END) - (DFU_REGION_START))
#define NRF_DFU_CURRENT_BANK_0 0x00
#define NRF_DFU_CURRENT_BANK_1 0x01
#define NRF_DFU_BANK_LAYOUT_DUAL 0x00
#define NRF_DFU_BANK_LAYOUT_SINGLE 0x01
/** @brief DFU bank state codes.
*
* @details The DFU bank state indicates the content of a bank:
* A valid image of a certain type or an invalid image.
*/
#define NRF_DFU_BANK_INVALID 0x00 /**< Invalid image. */
#define NRF_DFU_BANK_VALID_APP 0x01 /**< Valid application. */
#define NRF_DFU_BANK_VALID_SD 0xA5 /**< Valid SoftDevice. */
#define NRF_DFU_BANK_VALID_BL 0xAA /**< Valid bootloader. */
#define NRF_DFU_BANK_VALID_SD_BL 0xAC /**< Valid SoftDevice and bootloader. */
/** @brief Description of a single bank. */
#pragma pack(4)
typedef struct
{
uint32_t image_size; /**< Size of the image in the bank. */
uint32_t image_crc; /**< CRC of the image. If set to 0, the CRC is ignored. */
uint32_t bank_code; /**< Identifier code for the bank. */
} nrf_dfu_bank_t;
/**@brief DFU progress.
*
* Be aware of the difference between objects and firmware images. A firmware image consists of multiple objects, each of a maximum size @ref DATA_OBJECT_MAX_SIZE.
*
* @note The union inside this struct is cleared when CREATE_OBJECT of command type is executed, and when there is a valid post-validation.
* In DFU activation (after reset) the @ref dfu_progress_t::update_start_address will be used in case of a SD/SD+BL update.
*/
ANON_UNIONS_ENABLE;
typedef struct
{
uint32_t command_size; /**< The size of the current init command stored in the DFU settings. */
uint32_t command_offset; /**< The offset of the currently received init command data. The offset will increase as the init command is received. */
uint32_t command_crc; /**< The calculated CRC of the init command (calculated after the transfer is completed). */
uint32_t data_object_size; /**< The size of the last object created. Note that this size is not the size of the whole firmware image.*/
union
{
struct
{
uint32_t firmware_image_crc; /**< CRC value of the current firmware (continuously calculated as data is received). */
uint32_t firmware_image_crc_last; /**< The CRC of the last executed object. */
uint32_t firmware_image_offset; /**< The offset of the current firmware image being transferred. Note that this offset is the offset in the entire firmware image and not only the current object. */
uint32_t firmware_image_offset_last;/**< The offset of the last executed object from the start of the firmware image. */
};
struct
{
uint32_t update_start_address; /**< Value indicating the start address of the new firmware (before copy). It's always used, but it's most important for an SD/SD+BL update where the SD changes size or if the DFU process had a power loss when updating a SD with changed size. */
};
};
} dfu_progress_t;
ANON_UNIONS_DISABLE;
/** @brief Event types in the bootloader and DFU process. */
typedef enum
{
NRF_DFU_EVT_DFU_INITIALIZED, /**< Starting DFU. */
NRF_DFU_EVT_TRANSPORT_ACTIVATED, /**< Transport activated (e.g. BLE connected, USB plugged in). */
NRF_DFU_EVT_TRANSPORT_DEACTIVATED, /**< Transport deactivated (e.g. BLE disconnected, USB plugged out). */
NRF_DFU_EVT_DFU_STARTED, /**< DFU process started. */
NRF_DFU_EVT_OBJECT_RECEIVED, /**< A DFU data object has been received. */
NRF_DFU_EVT_DFU_FAILED, /**< DFU process has failed, been interrupted, or hung. */
NRF_DFU_EVT_DFU_COMPLETED, /**< DFU process completed. */
NRF_DFU_EVT_DFU_ABORTED, /**< DFU process aborted. */
} nrf_dfu_evt_type_t;
/**
* @brief Function for notifying DFU state.
*/
typedef void (*nrf_dfu_observer_t)(nrf_dfu_evt_type_t notification);
#if defined(NRF_DFU_TRANSPORT_BLE) && NRF_DFU_TRANSPORT_BLE
typedef struct
{
uint32_t crc; /**< CRC of the rest of the parameters in this struct. */
ble_gap_id_key_t ble_id; /**< BLE GAP identity key of the device that initiated the DFU process. */
ble_gap_enc_key_t enc_key; /**< Encryption key structure containing encrypted diversifier and LTK for reestablishing the bond. */
uint8_t sys_serv_attr[SYSTEM_SERVICE_ATT_SIZE]; /**< System service attributes for restoring of Service Changed Indication setting in DFU mode. */
} nrf_dfu_peer_data_t;
typedef enum
{
DFU_PEER_DATA_STATE_INVALID = 0,
DFU_PEER_DATA_STATE_INITIALIZED = 1,
DFU_PEER_DATA_STATE_WRITE_REQUESTED = 2,
DFU_PEER_DATA_STATE_WRITE_FINISHED = 3,
DFU_PEER_DATA_STATE_WRITE_FAILED = 4,
} nrf_dfu_peer_data_state_t;
typedef struct
{
uint32_t crc; /**< CRC of the rest of the parameters in this struct. Calculated by the bootloader. */
uint8_t name[20]; /**< New advertisement name to set. */
uint32_t len; /**< Length of the advertisement name. */
} nrf_dfu_adv_name_t;
typedef enum
{
DFU_ADV_NAME_STATE_INVALID = 0,
DFU_ADV_NAME_STATE_INITIALIZED = 1,
DFU_ADV_NAME_STATE_WRITE_REQUESTED = 2,
DFU_ADV_NAME_STATE_WRITE_FINISHED = 3,
DFU_ADV_NAME_STATE_WRITE_FAILED = 4,
} nrf_dfu_set_adv_name_state_t;
#endif // NRF_DFU_TRANSPORT_BLE
/**@brief DFU settings for application and bank data.
*/
typedef struct
{
uint32_t crc; /**< CRC for the stored DFU settings, not including the CRC itself. If 0xFFFFFFF, the CRC has never been calculated. */
uint32_t settings_version; /**< Version of the current DFU settings struct layout. */
uint32_t app_version; /**< Version of the last stored application. */
uint32_t bootloader_version; /**< Version of the last stored bootloader. */
uint32_t bank_layout; /**< Bank layout: single bank or dual bank. This value can change. */
uint32_t bank_current; /**< The bank that is currently used. */
nrf_dfu_bank_t bank_0; /**< Bank 0. */
nrf_dfu_bank_t bank_1; /**< Bank 1. */
uint32_t write_offset; /**< Write offset for the current operation. */
uint32_t sd_size; /**< Size of the SoftDevice. */
dfu_progress_t progress; /**< Current DFU progress. */
uint32_t enter_buttonless_dfu;
uint8_t init_command[INIT_COMMAND_MAX_SIZE]; /**< Buffer for storing the init command. */
#if defined(NRF_DFU_TRANSPORT_BLE) && NRF_DFU_TRANSPORT_BLE
nrf_dfu_peer_data_t peer_data; /**< Not included in calculated CRC. */
nrf_dfu_adv_name_t adv_name; /**< Not included in calculated CRC. */
#endif // NRF_DFU_TRANSPORT_BLE
} nrf_dfu_settings_t;
#pragma pack() // revert pack settings
#ifdef __cplusplus
}
#endif
#endif // NRF_DFU_TYPES_H__
/** @} */

View File

@ -0,0 +1,188 @@
/**
* Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**@file
*
* @defgroup nrf_bootloader_info Bootloader Information
* @{
* @ingroup nrf_bootloader
*/
#ifndef NRF_BOOTLOADER_INFO_H__
#define NRF_BOOTLOADER_INFO_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "app_util.h"
#include "nrf.h"
#include "nrf_mbr.h"
/** @brief Macro for getting the start address of the bootloader image.
*
* The macro is not a compile time symbol. It cannot be used as a
* constant expression, for example, inside a static assert or linker script
* at-placement.
*/
#ifndef BOOTLOADER_START_ADDR
#if (__LINT__ == 1)
#define BOOTLOADER_START_ADDR (0x3AC00)
#elif defined(CODE_START)
#define BOOTLOADER_START_ADDR (CODE_START)
#else
#error Not a valid compiler/linker for BOOTLOADER_START_ADDR.
#endif
#endif
/** @brief Macro for getting the size of the bootloader image.
*/
#ifndef BOOTLOADER_SIZE
#if defined ( NRF51 )
#define BOOTLOADER_SIZE (BOOTLOADER_SETTINGS_ADDRESS - BOOTLOADER_START_ADDR)
#elif defined( NRF52_SERIES )
#define BOOTLOADER_SIZE (NRF_MBR_PARAMS_PAGE_ADDRESS - BOOTLOADER_START_ADDR)
#elif (__LINT__ == 1)
#define BOOTLOADER_SIZE (0x6000)
#endif
#endif
/**
* @brief Bootloader start address in UICR.
*
* Register location in UICR where the bootloader start address is stored.
*
* @note If the value at the given location is 0xFFFFFFFF, the bootloader address is not set.
*/
#define NRF_UICR_BOOTLOADER_START_ADDRESS (NRF_UICR_BASE + 0x14)
// The following macros are for accessing the SoftDevice information structure,
// which is found inside the SoftDevice binary.
/** @brief Macro for converting an offset inside the SoftDevice information struct to an absolute address.
*/
#define SD_INFO_ABS_OFFSET_GET(baseaddr, offset) ((baseaddr) + (SOFTDEVICE_INFO_STRUCT_OFFSET) + (offset))
/** @brief Macros for reading a byte or a word at a particular offset inside a SoftDevice information struct.
* Use MBR_SIZE as baseaddr when the SoftDevice is installed just above the MBR (the usual case).
*/
#define SD_OFFSET_GET_UINT32(baseaddr, offset) (*((uint32_t *) SD_INFO_ABS_OFFSET_GET(baseaddr, offset)))
#define SD_OFFSET_GET_UINT16(baseaddr, offset) (*((uint16_t *) SD_INFO_ABS_OFFSET_GET(baseaddr, offset)))
#define SD_OFFSET_GET_UINT8(baseaddr, offset) (*((uint8_t *) SD_INFO_ABS_OFFSET_GET(baseaddr, offset)))
#ifdef BLE_STACK_SUPPORT_REQD
#include "nrf_sdm.h"
#else
/** @brief The offset inside the SoftDevice at which the information struct is placed.
* To see the layout of the information struct, see the SoftDevice specification.
*/
#define SOFTDEVICE_INFO_STRUCT_OFFSET (0x2000)
#define SD_INFO_STRUCT_SIZE(baseaddr) SD_OFFSET_GET_UINT8(baseaddr, 0x00)
/** @brief Macro for reading the size of a SoftDevice at a given base address.
*/
#ifndef SD_SIZE_GET
#define SD_SIZE_GET(baseaddr) SD_OFFSET_GET_UINT32(baseaddr, 0x08)
#endif
/** @brief Macro for reading the version of a SoftDevice at a given base address.
* This expression checks the length of the information struct to see if the version is present.
* The version number is constructed like this:
* major_version * 1000000 + minor_version * 1000 + bugfix_version
*/
#ifndef SD_VERSION_GET
#define SD_VERSION_GET(baseaddr) ((SD_INFO_STRUCT_SIZE(baseaddr) > (0x14)) \
? SD_OFFSET_GET_UINT32(baseaddr, 0x14) \
: 0)
#endif
#endif
/** @brief Macro for reading the magic number of a SoftDevice at a given base address.
*/
#ifndef SD_MAGIC_NUMBER_GET
#define SD_MAGIC_NUMBER_GET(baseaddr) SD_OFFSET_GET_UINT32(baseaddr, 0x04)
#endif
/** @brief Macro for getting the absolute address of the magic number.
*/
#define SD_MAGIC_NUMBER_ABS_OFFSET_GET(baseaddr) SD_INFO_ABS_OFFSET_GET(baseaddr, 0x04)
/** @brief The number present at a specific location in all SoftDevices.
*/
#define SD_MAGIC_NUMBER ((uint32_t)0x51B1E5DB)
/** @brief Whether a SoftDevice is at its regular location.
*/
#ifndef SD_PRESENT
#define SD_PRESENT ((SD_MAGIC_NUMBER_GET(MBR_SIZE)) == (SD_MAGIC_NUMBER))
#endif
/** @brief The multiplier for the major version of the SoftDevice. See \ref SD_VERSION_GET
*/
#define SD_MAJOR_VERSION_MULTIPLIER (1000000)
/** @brief Read the major version of the SoftDevice from the raw version number. See \ref SD_VERSION_GET.
*/
#define SD_MAJOR_VERSION_EXTRACT(raw_version) ((raw_version)/SD_MAJOR_VERSION_MULTIPLIER)
#define BOOTLOADER_DFU_GPREGRET_MASK (0xB0) /**< Magic pattern written to GPREGRET register to signal between main app and DFU. The 3 lower bits are assumed to be used for signalling purposes.*/
#define BOOTLOADER_DFU_START_BIT_MASK (0x01) /**< Bit mask to signal from main application to enter DFU mode using a buttonless service. */
#define BOOTLOADER_DFU_GPREGRET2_MASK (0xA8) /**< Magic pattern written to GPREGRET2 register to signal between main app and DFU. The 3 lower bits are assumed to be used for signalling purposes.*/
#define BOOTLOADER_DFU_SKIP_CRC_BIT_MASK (0x01) /**< Bit mask to signal from main application that CRC-check is not needed for image verification. */
#define BOOTLOADER_DFU_START (BOOTLOADER_DFU_GPREGRET_MASK | BOOTLOADER_DFU_START_BIT_MASK) /**< Magic number to signal that bootloader should enter DFU mode because of signal from Buttonless DFU in main app.*/
#define BOOTLOADER_DFU_SKIP_CRC (BOOTLOADER_DFU_GPREGRET2_MASK | BOOTLOADER_DFU_SKIP_CRC_BIT_MASK) /**< Magic number to signal that CRC can be skipped due to low power modes.*/
#ifdef __cplusplus
}
#endif
#endif // #ifndef NRF_BOOTLOADER_INFO_H__
/** @} */

View File

@ -0,0 +1,430 @@
/**
* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_SDH)
#include "nrf_sdh.h"
#include <stdint.h>
#include "nrf_sdm.h"
#include "nrf_nvic.h"
#include "sdk_config.h"
#include "app_error.h"
#include "app_util_platform.h"
#define NRF_LOG_MODULE_NAME nrf_sdh
#if NRF_SDH_LOG_ENABLED
#define NRF_LOG_LEVEL NRF_SDH_LOG_LEVEL
#define NRF_LOG_INFO_COLOR NRF_SDH_INFO_COLOR
#define NRF_LOG_DEBUG_COLOR NRF_SDH_DEBUG_COLOR
#else
#define NRF_LOG_LEVEL 0
#endif // NRF_SDH_LOG_ENABLED
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
// Validate configuration options.
#if (NRF_SDH_DISPATCH_MODEL == NRF_SDH_DISPATCH_MODEL_APPSH)
#if (!APP_SCHEDULER_ENABLED)
#error app_scheduler is required when NRF_SDH_DISPATCH_MODEL is set to NRF_SDH_DISPATCH_MODEL_APPSH
#endif
#include "app_scheduler.h"
#endif
#if ( (NRF_SDH_CLOCK_LF_SRC == NRF_CLOCK_LF_SRC_RC) \
&& (NRF_SDH_CLOCK_LF_ACCURACY != NRF_CLOCK_LF_ACCURACY_500_PPM))
#warning Please select NRF_CLOCK_LF_ACCURACY_500_PPM when using NRF_CLOCK_LF_SRC_RC
#endif
// Create section "sdh_req_observers".
NRF_SECTION_SET_DEF(sdh_req_observers, nrf_sdh_req_observer_t, NRF_SDH_REQ_OBSERVER_PRIO_LEVELS);
// Create section "sdh_state_observers".
NRF_SECTION_SET_DEF(sdh_state_observers, nrf_sdh_state_observer_t, NRF_SDH_STATE_OBSERVER_PRIO_LEVELS);
// Create section "sdh_stack_observers".
NRF_SECTION_SET_DEF(sdh_stack_observers, nrf_sdh_stack_observer_t, NRF_SDH_STACK_OBSERVER_PRIO_LEVELS);
static bool m_nrf_sdh_enabled; /**< Variable to indicate whether the SoftDevice is enabled. */
static bool m_nrf_sdh_suspended; /**< Variable to indicate whether this module is suspended. */
static bool m_nrf_sdh_continue; /**< Variable to indicate whether enable/disable process was started. */
/**@brief Function for notifying request observers.
*
* @param[in] evt Type of request event.
*/
static ret_code_t sdh_request_observer_notify(nrf_sdh_req_evt_t req)
{
nrf_section_iter_t iter;
NRF_LOG_DEBUG("State request: 0x%08X", req);
for (nrf_section_iter_init(&iter, &sdh_req_observers);
nrf_section_iter_get(&iter) != NULL;
nrf_section_iter_next(&iter))
{
nrf_sdh_req_observer_t * p_observer;
nrf_sdh_req_evt_handler_t handler;
p_observer = (nrf_sdh_req_observer_t *) nrf_section_iter_get(&iter);
handler = p_observer->handler;
if (handler(req, p_observer->p_context))
{
NRF_LOG_DEBUG("Notify observer 0x%08X => ready", p_observer);
}
else
{
// Process is stopped.
NRF_LOG_DEBUG("Notify observer 0x%08X => blocking", p_observer);
return NRF_ERROR_BUSY;
}
}
return NRF_SUCCESS;
}
/**@brief Function for stage request observers.
*
* @param[in] evt Type of stage event.
*/
static void sdh_state_observer_notify(nrf_sdh_state_evt_t evt)
{
nrf_section_iter_t iter;
NRF_LOG_DEBUG("State change: 0x%08X", evt);
for (nrf_section_iter_init(&iter, &sdh_state_observers);
nrf_section_iter_get(&iter) != NULL;
nrf_section_iter_next(&iter))
{
nrf_sdh_state_observer_t * p_observer;
nrf_sdh_state_evt_handler_t handler;
p_observer = (nrf_sdh_state_observer_t *) nrf_section_iter_get(&iter);
handler = p_observer->handler;
handler(evt, p_observer->p_context);
}
}
static void softdevices_evt_irq_enable(void)
{
#ifdef SOFTDEVICE_PRESENT
ret_code_t ret_code = sd_nvic_EnableIRQ((IRQn_Type)SD_EVT_IRQn);
APP_ERROR_CHECK(ret_code);
#else
// In case of serialization, NVIC must be accessed directly.
NVIC_EnableIRQ(SD_EVT_IRQn);
#endif
}
static void softdevice_evt_irq_disable(void)
{
#ifdef SOFTDEVICE_PRESENT
ret_code_t ret_code = sd_nvic_DisableIRQ((IRQn_Type)SD_EVT_IRQn);
APP_ERROR_CHECK(ret_code);
#else
// In case of serialization, NVIC must be accessed directly.
NVIC_DisableIRQ(SD_EVT_IRQn);
#endif
}
#ifndef S140
static void swi_interrupt_priority_workaround(void)
{
// The priority of SoftDevice SWI SD_EVT_IRQn and RADIO_NOTIFICATION_IRQn in
// S132 v5.0.0, S112 v5.0.0, S212 v5.0.0 and S332 v5.0.0 is set to 6.
// Change it to APP_IRQ_PRIORITY_LOWEST (7) so that they do not preempt peripherals' interrupts.
#ifdef SOFTDEVICE_PRESENT
ret_code_t ret_code;
ret_code = sd_nvic_SetPriority(SD_EVT_IRQn, APP_IRQ_PRIORITY_LOWEST);
APP_ERROR_CHECK(ret_code);
ret_code = sd_nvic_SetPriority(RADIO_NOTIFICATION_IRQn, APP_IRQ_PRIORITY_LOWEST);
APP_ERROR_CHECK(ret_code);
#else
// In case of serialization, NVIC must be accessed directly.
NVIC_SetPriority(SD_EVT_IRQn, APP_IRQ_PRIORITY_LOWEST);
NVIC_SetPriority(RADIO_NOTIFICATION_IRQn, APP_IRQ_PRIORITY_LOWEST);
#endif
}
#endif
ret_code_t nrf_sdh_enable_request(void)
{
ret_code_t ret_code;
if (m_nrf_sdh_enabled)
{
return NRF_ERROR_INVALID_STATE;
}
m_nrf_sdh_continue = true;
// Notify observers about SoftDevice enable request.
if (sdh_request_observer_notify(NRF_SDH_EVT_ENABLE_REQUEST) == NRF_ERROR_BUSY)
{
// Enable process was stopped.
return NRF_SUCCESS;
}
// Notify observers about starting SoftDevice enable process.
sdh_state_observer_notify(NRF_SDH_EVT_STATE_ENABLE_PREPARE);
nrf_clock_lf_cfg_t const clock_lf_cfg =
{
.source = NRF_SDH_CLOCK_LF_SRC,
.rc_ctiv = NRF_SDH_CLOCK_LF_RC_CTIV,
.rc_temp_ctiv = NRF_SDH_CLOCK_LF_RC_TEMP_CTIV,
.accuracy = NRF_SDH_CLOCK_LF_ACCURACY
};
CRITICAL_REGION_ENTER();
#ifdef ANT_LICENSE_KEY
ret_code = sd_softdevice_enable(&clock_lf_cfg, app_error_fault_handler, ANT_LICENSE_KEY);
#else
ret_code = sd_softdevice_enable(&clock_lf_cfg, app_error_fault_handler);
#endif
m_nrf_sdh_enabled = (ret_code == NRF_SUCCESS);
CRITICAL_REGION_EXIT();
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
m_nrf_sdh_continue = false;
m_nrf_sdh_suspended = false;
#ifndef S140
// Set the interrupt priority after enabling the SoftDevice, since
// sd_softdevice_enable() sets the SoftDevice interrupt priority.
swi_interrupt_priority_workaround();
#endif
// Enable event interrupt.
// Interrupt priority has already been set by the stack.
softdevices_evt_irq_enable();
// Notify observers about a finished SoftDevice enable process.
sdh_state_observer_notify(NRF_SDH_EVT_STATE_ENABLED);
return NRF_SUCCESS;
}
ret_code_t nrf_sdh_disable_request(void)
{
ret_code_t ret_code;
if (!m_nrf_sdh_enabled)
{
return NRF_ERROR_INVALID_STATE;
}
m_nrf_sdh_continue = true;
// Notify observers about SoftDevice disable request.
if (sdh_request_observer_notify(NRF_SDH_EVT_DISABLE_REQUEST) == NRF_ERROR_BUSY)
{
// Disable process was stopped.
return NRF_SUCCESS;
}
// Notify observers about starting SoftDevice disable process.
sdh_state_observer_notify(NRF_SDH_EVT_STATE_DISABLE_PREPARE);
CRITICAL_REGION_ENTER();
ret_code = sd_softdevice_disable();
m_nrf_sdh_enabled = false;
CRITICAL_REGION_EXIT();
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
m_nrf_sdh_continue = false;
softdevice_evt_irq_disable();
// Notify observers about a finished SoftDevice enable process.
sdh_state_observer_notify(NRF_SDH_EVT_STATE_DISABLED);
return NRF_SUCCESS;
}
ret_code_t nrf_sdh_request_continue(void)
{
if (!m_nrf_sdh_continue)
{
return NRF_ERROR_INVALID_STATE;
}
if (m_nrf_sdh_enabled)
{
return nrf_sdh_disable_request();
}
else
{
return nrf_sdh_enable_request();
}
}
bool nrf_sdh_is_enabled(void)
{
return m_nrf_sdh_enabled;
}
void nrf_sdh_suspend(void)
{
if (!m_nrf_sdh_enabled)
{
return;
}
softdevice_evt_irq_disable();
m_nrf_sdh_suspended = true;
}
void nrf_sdh_resume(void)
{
if ((!m_nrf_sdh_suspended) || (!m_nrf_sdh_enabled))
{
return;
}
// Force calling ISR again to make sure that events not previously pulled have been processed.
#ifdef SOFTDEVICE_PRESENT
ret_code_t ret_code = sd_nvic_SetPendingIRQ((IRQn_Type)SD_EVT_IRQn);
APP_ERROR_CHECK(ret_code);
#else
NVIC_SetPendingIRQ((IRQn_Type)SD_EVT_IRQn);
#endif
softdevices_evt_irq_enable();
m_nrf_sdh_suspended = false;
}
bool nrf_sdh_is_suspended(void)
{
return (!m_nrf_sdh_enabled) || (m_nrf_sdh_suspended);
}
void nrf_sdh_evts_poll(void)
{
nrf_section_iter_t iter;
// Notify observers about pending SoftDevice event.
for (nrf_section_iter_init(&iter, &sdh_stack_observers);
nrf_section_iter_get(&iter) != NULL;
nrf_section_iter_next(&iter))
{
nrf_sdh_stack_observer_t * p_observer;
nrf_sdh_stack_evt_handler_t handler;
p_observer = (nrf_sdh_stack_observer_t *) nrf_section_iter_get(&iter);
handler = p_observer->handler;
handler(p_observer->p_context);
}
}
#if (NRF_SDH_DISPATCH_MODEL == NRF_SDH_DISPATCH_MODEL_INTERRUPT)
void SD_EVT_IRQHandler(void)
{
nrf_sdh_evts_poll();
}
#elif (NRF_SDH_DISPATCH_MODEL == NRF_SDH_DISPATCH_MODEL_APPSH)
/**@brief Function for polling SoftDevice events.
*
* @note This function is compatible with @ref app_sched_event_handler_t.
*
* @param[in] p_event_data Pointer to the event data.
* @param[in] event_size Size of the event data.
*/
static void appsh_events_poll(void * p_event_data, uint16_t event_size)
{
UNUSED_PARAMETER(p_event_data);
UNUSED_PARAMETER(event_size);
nrf_sdh_evts_poll();
}
void SD_EVT_IRQHandler(void)
{
ret_code_t ret_code = app_sched_event_put(NULL, 0, appsh_events_poll);
APP_ERROR_CHECK(ret_code);
}
#elif (NRF_SDH_DISPATCH_MODEL == NRF_SDH_DISPATCH_MODEL_POLLING)
#else
#error "Unknown SoftDevice handler dispatch model."
#endif // NRF_SDH_DISPATCH_MODEL
#endif // NRF_MODULE_ENABLED(NRF_SDH)

View File

@ -0,0 +1,305 @@
/**
* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** @file
*
* @defgroup nrf_sdh SoftDevice Handler
* @{
* @ingroup app_common
* @brief API for initializing and disabling the SoftDevice.
*/
#ifndef NRF_SDH_H__
#define NRF_SDH_H__
#include <stdbool.h>
#include "sdk_config.h"
#include "sdk_errors.h"
#include "nrf_section_iter.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @name Softdevice Handler dispatch models
* @{
* @ingroup nrf_sdh */
/**@brief SoftDevice events are passed to the application from the interrupt context. */
#define NRF_SDH_DISPATCH_MODEL_INTERRUPT 0
/**@brief SoftDevice events are passed to the application using @ref app_scheduler.
*
* @note @ref app_scheduler must be initialized before enabling the SoftDevice handler.
*/
#define NRF_SDH_DISPATCH_MODEL_APPSH 1
/**@brief SoftDevice events are polled manually using @ref nrf_sdh_evts_poll().
*
* @note In this mode, a user application can also implement SD_EVT_IRQHandler() to receive a
* notification about incoming events.
*/
#define NRF_SDH_DISPATCH_MODEL_POLLING 2
/** @} */
/**
* @name SoftDevice Handler state change requests
* @{
* @ingroup nrf_sdh */
/**@brief SoftDevice Handler state requests. */
typedef enum
{
NRF_SDH_EVT_ENABLE_REQUEST, //!< Request to enable the SoftDevice.
NRF_SDH_EVT_DISABLE_REQUEST, //!< Request to disable the SoftDevice.
} nrf_sdh_req_evt_t;
/**@brief SoftDevice Handler state request handler.
*
* @retval true If ready for the SoftDevice to change state.
* @retval false If not ready for the SoftDevice to change state.
* If false is returned, the state change is aborted.
*/
typedef bool (*nrf_sdh_req_evt_handler_t)(nrf_sdh_req_evt_t request, void * p_context);
/**@brief SoftDevice Handler state request observer. */
typedef struct
{
nrf_sdh_req_evt_handler_t handler; //!< Request handler.
void * p_context; //!< A parameter to the handler function.
} const nrf_sdh_req_observer_t;
/**@brief Macro for registering a SoftDevice state change request observer.
*
* An observer of SoftDevice state change requests receives requests to change the state of the
* SoftDevice from enabled to disabled and vice versa. These requests may or may not be acknowledged
* by the observer, depending on the value returned by its request handler function. Thus, a
* request observer has the capability to defer the change of state of the SoftDevice. If it does
* so, it has the responsibility to call @ref nrf_sdh_request_continue when it is ready to let the
* SoftDevice change its state. If such capability is not necessary and you only need to be informed
* about changes of the SoftDevice state, use the @ref NRF_SDH_STATE_OBSERVER macro instead.
*
* @note This macro places the observer in a section named "sdh_req_observers".
*
* @param[in] _observer Name of the observer.
* @param[in] _prio Priority of the observer's event handler.
* The smaller the number, the higher the priority.
* @hideinitializer
*/
#define NRF_SDH_REQUEST_OBSERVER(_observer, _prio) \
STATIC_ASSERT(NRF_SDH_ENABLED, "NRF_SDH_ENABLED not set!"); \
STATIC_ASSERT(_prio < NRF_SDH_REQ_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \
/*lint -esym(528,*_observer) -esym(529,*_observer) : Symbol not referenced. */ \
NRF_SECTION_SET_ITEM_REGISTER(sdh_req_observers, _prio, nrf_sdh_req_observer_t const _observer)
/** @} */
/**
* @name SoftDevice Handler state events
* @{
* @ingroup nrf_sdh */
/**@brief SoftDevice Handler state events. */
typedef enum
{
NRF_SDH_EVT_STATE_ENABLE_PREPARE, //!< SoftDevice is going to be enabled.
NRF_SDH_EVT_STATE_ENABLED, //!< SoftDevice is enabled.
NRF_SDH_EVT_STATE_DISABLE_PREPARE, //!< SoftDevice is going to be disabled.
NRF_SDH_EVT_STATE_DISABLED, //!< SoftDevice is disabled.
} nrf_sdh_state_evt_t;
/**@brief SoftDevice Handler state event handler. */
typedef void (*nrf_sdh_state_evt_handler_t)(nrf_sdh_state_evt_t state, void * p_context);
/**@brief SoftDevice Handler state observer. */
typedef struct
{
nrf_sdh_state_evt_handler_t handler; //!< State event handler.
void * p_context; //!< A parameter to the event handler.
} const nrf_sdh_state_observer_t;
/**@brief Macro for registering a SoftDevice state observer.
*
* A SoftDevice state observer receives events when the SoftDevice state has changed or is
* about to change. These events are only meant to inform the state observer, which, contrary
* to a state change request observer, does not have the capability to defer the change of state.
* If such capability is required, use the @ref NRF_SDH_REQUEST_OBSERVER macro instead.
*
* This macro places the observer in a section named "sdh_state_observers".
*
* @param[in] _observer Name of the observer.
* @param[in] _prio Priority of the observer's event handler.
* The smaller the number, the higher the priority.
* @hideinitializer
*/
#define NRF_SDH_STATE_OBSERVER(_observer, _prio) \
STATIC_ASSERT(NRF_SDH_ENABLED, "NRF_SDH_ENABLED not set!"); \
STATIC_ASSERT(_prio < NRF_SDH_STATE_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \
/*lint -esym(528,*_observer) -esym(529,*_observer) : Symbol not referenced. */ \
NRF_SECTION_SET_ITEM_REGISTER(sdh_state_observers, _prio, static nrf_sdh_state_observer_t const _observer)
/** @} */
/**
* @name SoftDevice stack events
* @{
* @ingroup nrf_sdh */
/**@brief SoftDevice stack event handler. */
typedef void (*nrf_sdh_stack_evt_handler_t)(void * p_evt);
/**@brief SoftDevice stack event observer. */
typedef struct
{
nrf_sdh_stack_evt_handler_t handler; //!< SoftDevice event handler.
void * p_context; //!< A parameter to the event handler.
} const nrf_sdh_stack_observer_t;
/**@brief Macro for registering a SoftDevice stack events observer.
*
* A SoftDevice stack event observer receives all events from the SoftDevice. These events can be
* either BLE, ANT, or SoC events. If you need to receive BLE, ANT, or SoC events separately, use the
* @ref NRF_SDH_BLE_OBSERVER, @ref NRF_SDH_ANT_OBSERVER, or @ref NRF_SDH_SOC_OBSERVER macros
* respectively.
*
* @note This macro places the observer in a section named "sdh_stack_observers".
*
* @param[in] _observer Name of the observer.
* @param[in] _prio Priority of the observer's event handler.
* The smaller the number, the higher the priority.
** @hideinitializer
*/
#define NRF_SDH_STACK_OBSERVER(_observer, _prio) \
STATIC_ASSERT(NRF_SDH_ENABLED, "NRF_SDH_ENABLED not set!"); \
STATIC_ASSERT(_prio < NRF_SDH_STACK_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \
/*lint -esym(528,*_observer) -esym(529,*_observer) : Symbol not referenced. */ \
NRF_SECTION_SET_ITEM_REGISTER(sdh_stack_observers, _prio, static nrf_sdh_stack_observer_t const _observer)
/** @} */
/**@brief Function for requesting to enable the SoftDevice.
*
* This function issues a @ref NRF_SDH_EVT_ENABLE_REQUEST request to all observers that
* were registered using the @ref NRF_SDH_REQUEST_OBSERVER macro. The observers may or
* may not acknowledge the request. If all observers acknowledge the request, the
* SoftDevice will be enabled. Otherwise, the process will be stopped and the observers
* that did not acknowledge have the responsibility to restart it by calling
* @ref nrf_sdh_request_continue when they are ready for the SoftDevice to change state.
*
* @retval NRF_SUCCESS The process is started.
* @retval NRF_ERROR_INVALID_STATE The SoftDevice is already enabled.
*/
ret_code_t nrf_sdh_enable_request(void);
/**@brief Function for requesting to disable the SoftDevice.
*
* This function issues a @ref NRF_SDH_EVT_DISABLE_REQUEST request to all observers that
* were registered using the @ref NRF_SDH_REQUEST_OBSERVER macro. The observers may or
* may not acknowledge the request. If all observers acknowledge the request, the
* SoftDevice will be disabled. Otherwise, the process will be stopped and the observers
* that did not acknowledge have the responsibility to restart it by calling
* @ref nrf_sdh_request_continue when they are ready for the SoftDevice to change state.
*
* @retval NRF_SUCCESS The process is started.
* @retval NRF_ERROR_INVALID_STATE The SoftDevice is already disabled.
*/
ret_code_t nrf_sdh_disable_request(void);
/**@brief Function for restarting the SoftDevice Enable/Disable process.
*
* Modules which did not acknowledge a @ref NRF_SDH_EVT_ENABLE_REQUEST or
* @ref NRF_SDH_EVT_DISABLE_REQUEST request must call this function to restart the
* SoftDevice state change process.
*
* @retval NRF_SUCCESS The process is restarted.
* @retval NRF_ERROR_INVALID_STATE No state change request was pending.
*/
ret_code_t nrf_sdh_request_continue(void);
/**@brief Function for retrieving the SoftDevice state.
*
* @retval true If the SoftDevice is enabled.
* @retval false If the SoftDevice is disabled.
*/
bool nrf_sdh_is_enabled(void);
/**@brief Function for stopping the incoming stack events.
*
* This function disables the SoftDevice interrupt. To resume polling for events,
* call @ref nrf_sdh_resume.
*/
void nrf_sdh_suspend(void);
/**@brief Function for resuming polling incoming events from the SoftDevice. */
void nrf_sdh_resume(void);
/**@brief Function for retrieving the information about the module state.
*
* @retval true The SoftDevice handler is paused, and it will not fetch events from the stack.
* @retval false The SoftDevice handler is running, and it will fetch and dispatch events from
* the stack to the registered stack observers.
*/
bool nrf_sdh_is_suspended(void);
/**@brief Function for polling stack events from the SoftDevice.
*
* The events are passed to the application using the registered event handlers.
*
* @note @ref NRF_SDH_DISPATCH_MODEL_POLLING must be selected to use this function.
*/
void nrf_sdh_evts_poll(void);
#ifdef __cplusplus
}
#endif
#endif // NRF_SDH_H__
/** @} */

View File

@ -0,0 +1,162 @@
/**
* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_SDH_ANT)
#include "nrf_sdh_ant.h"
#include "nrf_sdh.h"
#include "app_error.h"
#include "nrf_strerror.h"
#include "ant_interface.h"
#define NRF_LOG_MODULE_NAME nrf_sdh_ant
#if NRF_SDH_ANT_LOG_ENABLED
#define NRF_LOG_LEVEL NRF_SDH_ANT_LOG_LEVEL
#define NRF_LOG_INFO_COLOR NRF_SDH_ANT_INFO_COLOR
#define NRF_LOG_DEBUG_COLOR NRF_SDH_ANT_DEBUG_COLOR
#else
#define NRF_LOG_LEVEL 0
#endif // NRF_SDH_ANT_LOG_ENABLED
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
STATIC_ASSERT(NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED <= MAX_ANT_CHANNELS);
STATIC_ASSERT(NRF_SDH_ANT_ENCRYPTED_CHANNELS <= NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED);
// Create section set "sdh_ant_observers".
NRF_SECTION_SET_DEF(sdh_ant_observers, nrf_sdh_ant_evt_observer_t, NRF_SDH_ANT_OBSERVER_PRIO_LEVELS);
// Memory buffer provided in order to support channel configuration.
__ALIGN(4) static uint8_t m_ant_stack_buffer[NRF_SDH_ANT_BUF_SIZE];
static bool m_stack_is_enabled;
ret_code_t nrf_sdh_ant_enable(void)
{
ANT_ENABLE ant_enable_cfg =
{
.ucTotalNumberOfChannels = NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED,
.ucNumberOfEncryptedChannels = NRF_SDH_ANT_ENCRYPTED_CHANNELS,
.usNumberOfEvents = NRF_SDH_ANT_EVENT_QUEUE_SIZE,
.pucMemoryBlockStartLocation = m_ant_stack_buffer,
.usMemoryBlockByteSize = sizeof(m_ant_stack_buffer),
};
ret_code_t ret_code = sd_ant_enable(&ant_enable_cfg);
if (ret_code == NRF_SUCCESS)
{
m_stack_is_enabled = true;
}
else
{
NRF_LOG_ERROR("sd_ant_enable() returned %s.", nrf_strerror_get(ret_code));
}
return ret_code;
}
/**@brief Function for polling ANT events.
*
* @param[in] p_context Context of the observer.
*/
static void nrf_sdh_ant_evts_poll(void * p_context)
{
UNUSED_VARIABLE(p_context);
ret_code_t ret_code;
#ifndef SER_CONNECTIVITY
if (!m_stack_is_enabled)
{
return;
}
#else
UNUSED_VARIABLE(m_stack_is_enabled);
#endif // SER_CONNECTIVITY
while (true)
{
ant_evt_t ant_evt;
ret_code = sd_ant_event_get(&ant_evt.channel, &ant_evt.event, ant_evt.message.aucMessage);
if (ret_code != NRF_SUCCESS)
{
break;
}
NRF_LOG_DEBUG("ANT Event 0x%02X Channel 0x%02X", ant_evt.event, ant_evt.channel);
// Forward the event to ANT observers.
nrf_section_iter_t iter;
for (nrf_section_iter_init(&iter, &sdh_ant_observers);
nrf_section_iter_get(&iter) != NULL;
nrf_section_iter_next(&iter))
{
nrf_sdh_ant_evt_observer_t * p_observer;
nrf_sdh_ant_evt_handler_t handler;
p_observer = (nrf_sdh_ant_evt_observer_t *) nrf_section_iter_get(&iter);
handler = p_observer->handler;
handler(&ant_evt, p_observer->p_context);
}
}
if (ret_code != NRF_ERROR_NOT_FOUND)
{
APP_ERROR_HANDLER(ret_code);
}
}
NRF_SDH_STACK_OBSERVER(m_nrf_sdh_ant_evts_poll, NRF_SDH_ANT_STACK_OBSERVER_PRIO) =
{
.handler = nrf_sdh_ant_evts_poll,
.p_context = NULL,
};
#endif // NRF_MODULE_ENABLED(NRF_SDH_ANT)

View File

@ -0,0 +1,182 @@
/**
* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**@file
*
* @defgroup nrf_sdh_ant ANT support in SoftDevice Handler
* @{
* @ingroup nrf_sdh
* @brief This file contains the declarations of types and functions required for ANT stack support.
*/
#ifndef NRF_SDH_ANT_H__
#define NRF_SDH_ANT_H__
#include "ant_parameters.h"
#include "app_util.h"
#include "nrf_section_iter.h"
#include "sdk_errors.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define NRF_SDH_ANT_EVT_CHANNEL_FIELD_SIZE 1 //!< Size of the channel field in ANT stack event
#define NRF_SDH_ANT_EVT_EVENT_FIELD_SIZE 1 //!< Size of the event field in ANT stack event
/**@brief Size of the buffer provided to the ANT SoftDevice.
* @hideinitializer
*/
#define NRF_SDH_ANT_BUF_SIZE ANT_ENABLE_GET_REQUIRED_SPACE( \
NRF_SDH_ANT_TOTAL_CHANNELS_ALLOCATED, \
NRF_SDH_ANT_ENCRYPTED_CHANNELS, \
NRF_SDH_ANT_BURST_QUEUE_SIZE, \
NRF_SDH_ANT_EVENT_QUEUE_SIZE)
/**@brief Size of the buffer provided to the ANT SoftDevice to receive ANT events. */
#define NRF_SDH_ANT_MESSAGE_SIZE ((CEIL_DIV(MESG_BUFFER_SIZE, sizeof(uint32_t))) * sizeof(uint32_t))
/**@brief Size of the buffer provided to the Events Scheduler to hold ANT events. */
#define NRF_SDH_ANT_EVT_BUF_SIZE ((CEIL_DIV(NRF_SDH_ANT_MESSAGE_SIZE + \
NRF_SDH_ANT_EVT_CHANNEL_FIELD_SIZE + \
NRF_SDH_ANT_EVT_EVENT_FIELD_SIZE, \
sizeof(uint32_t))) * sizeof(uint32_t))
#if !(defined(__LINT__))
/**@brief Macro for registering an ANT observer. Modules that want to be
* notified about ANT events must register the handler using this macro.
*
* @details This macro places the observer in a section named "sdh_ant_observers".
*
* @param[in] _name Observer name.
* @param[in] _prio Priority of the observer event handler.
* The smaller the number, the higher the priority.
* @param[in] _handler ANT event handler.
* @param[in] _context Parameter to the event handler.
* @hideinitializer
*/
#define NRF_SDH_ANT_OBSERVER(_name, _prio, _handler, _context) \
STATIC_ASSERT(NRF_SDH_ANT_ENABLED, "NRF_SDH_ANT_ENABLED not set!"); \
STATIC_ASSERT(_prio < NRF_SDH_ANT_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \
NRF_SECTION_SET_ITEM_REGISTER(sdh_ant_observers, _prio, static nrf_sdh_ant_evt_observer_t _name) = \
{ \
.handler = _handler, \
.p_context = _context \
}
/**@brief Macro for registering an array of @ref nrf_sdh_ant_evt_observer_t.
* Modules that want to be notified about ANT events must register the handler using
* this macro.
*
* Each observer's handler will be dispatched an event with its relative context from @p _context.
* This macro places the observer in a section named "sdh_ant_observers".
*
* @param[in] _name Observer name.
* @param[in] _prio Priority of the observer event handler.
* The smaller the number, the higher the priority.
* @param[in] _handler ANT event handler.
* @param[in] _context An array of parameters to the event handler.
* @param[in] _cnt Number of observers to register.
* @hideinitializer
*/
#define NRF_SDH_ANT_OBSERVERS(_name, _prio, _handler, _context, _cnt) \
STATIC_ASSERT(NRF_SDH_ANT_ENABLED, "NRF_SDH_ANT_ENABLED not set!"); \
STATIC_ASSERT(_prio < NRF_SDH_ANT_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \
NRF_SECTION_SET_ITEM_REGISTER(sdh_ant_observers, _prio, static nrf_sdh_ant_evt_observer_t _name[_cnt]) = \
{ \
MACRO_REPEAT_FOR(_cnt, HANDLER_SET, _handler, _context) \
}
#if !(defined(DOXYGEN))
#define HANDLER_SET(_idx, _handler, _context) \
{ \
.handler = _handler, \
.p_context = _context[_idx], \
},
#endif
#else // __LINT__
/* Swallow semicolons */
/*lint -save -esym(528, *) -esym(529, *) : Symbol not referenced. */
#define NRF_SDH_ANT_OBSERVER(A, B, C, D) static int semicolon_swallow_##A
#define NRF_SDH_ANT_OBSERVERS(A, B, C, D, E) static int semicolon_swallow_##A
/*lint -restore */
#endif
/**@brief ANT stack event. */
typedef struct
{
ANT_MESSAGE message; //!< ANT Message.
uint8_t channel; //!< Channel number.
uint8_t event; //!< Event code.
} ant_evt_t;
/**@brief ANT stack event handler. */
typedef void (*nrf_sdh_ant_evt_handler_t)(ant_evt_t * p_ant_evt, void * p_context);
/**@brief ANT event observer. */
typedef struct
{
nrf_sdh_ant_evt_handler_t handler; //!< ANT event handler.
void * p_context; //!< A parameter to the event handler.
} const nrf_sdh_ant_evt_observer_t;
/**@brief Function for configuring and enabling the ANT stack.
*
* @details The function sets the channel configuration for the stack using the parameters
* provided in the @c sdk_config file. It also assigns a correspondingly large
* buffer as a static resource.
*/
ret_code_t nrf_sdh_ant_enable(void);
#ifdef __cplusplus
}
#endif
#endif // NRF_SDH_ANT_H__
/** @} */

View File

@ -0,0 +1,324 @@
/**
* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_SDH_BLE)
#include "nrf_sdh_ble.h"
#include "nrf_sdh.h"
#include "app_error.h"
#include "nrf_strerror.h"
#define NRF_LOG_MODULE_NAME nrf_sdh_ble
#if NRF_SDH_BLE_LOG_ENABLED
#define NRF_LOG_LEVEL NRF_SDH_BLE_LOG_LEVEL
#define NRF_LOG_INFO_COLOR NRF_SDH_BLE_INFO_COLOR
#define NRF_LOG_DEBUG_COLOR NRF_SDH_BLE_DEBUG_COLOR
#else
#define NRF_LOG_LEVEL 0
#endif // NRF_SDH_BLE_LOG_ENABLED
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
// Create section set "sdh_ble_observers".
NRF_SECTION_SET_DEF(sdh_ble_observers, nrf_sdh_ble_evt_observer_t, NRF_SDH_BLE_OBSERVER_PRIO_LEVELS);
//lint -save -e10 -e19 -e40 -e27 Illegal character (0x24)
#if defined(__CC_ARM)
extern uint32_t Image$$RW_IRAM1$$Base;
uint32_t const * const m_ram_start = &Image$$RW_IRAM1$$Base;
#elif defined(__ICCARM__)
extern uint32_t __ICFEDIT_region_RAM_start__;
uint32_t const * const m_ram_start = &__ICFEDIT_region_RAM_start__;
#elif defined(__SES_ARM)
extern uint32_t __app_ram_start__;
uint32_t const * const m_ram_start = &__app_ram_start__;
#elif defined(__GNUC__)
extern uint32_t __data_start__;
uint32_t const * const m_ram_start = &__data_start__;
#endif
//lint -restore
#define RAM_START 0x20000000
#define APP_RAM_START (uint32_t)m_ram_start
static bool m_stack_is_enabled;
ret_code_t nrf_sdh_ble_app_ram_start_get(uint32_t * p_app_ram_start)
{
if (p_app_ram_start == NULL)
{
return NRF_ERROR_NULL;
}
*p_app_ram_start = APP_RAM_START;
return NRF_SUCCESS;
}
ret_code_t nrf_sdh_ble_default_cfg_set(uint8_t conn_cfg_tag, uint32_t * p_ram_start)
{
uint32_t ret_code;
ret_code = nrf_sdh_ble_app_ram_start_get(p_ram_start);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
#ifdef S112
STATIC_ASSERT(NRF_SDH_BLE_CENTRAL_LINK_COUNT == 0, "When using s112, NRF_SDH_BLE_CENTRAL_LINK_COUNT must be 0.");
#endif
// Overwrite some of the default settings of the BLE stack.
// If any of the calls to sd_ble_cfg_set() fail, log the error but carry on so that
// wrong RAM settings can be caught by nrf_sdh_ble_enable() and a meaningful error
// message will be printed to the user suggesting the correct value.
ble_cfg_t ble_cfg;
#if (NRF_SDH_BLE_TOTAL_LINK_COUNT != 0)
// Configure the connection count.
memset(&ble_cfg, 0, sizeof(ble_cfg));
ble_cfg.conn_cfg.conn_cfg_tag = conn_cfg_tag;
ble_cfg.conn_cfg.params.gap_conn_cfg.conn_count = NRF_SDH_BLE_TOTAL_LINK_COUNT;
ble_cfg.conn_cfg.params.gap_conn_cfg.event_length = NRF_SDH_BLE_GAP_EVENT_LENGTH;
ret_code = sd_ble_cfg_set(BLE_CONN_CFG_GAP, &ble_cfg, *p_ram_start);
if (ret_code != NRF_SUCCESS)
{
NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_CONN_CFG_GAP.",
nrf_strerror_get(ret_code));
}
// Configure the connection roles.
memset(&ble_cfg, 0, sizeof(ble_cfg));
ble_cfg.gap_cfg.role_count_cfg.periph_role_count = NRF_SDH_BLE_PERIPHERAL_LINK_COUNT;
#ifndef S112
ble_cfg.gap_cfg.role_count_cfg.central_role_count = NRF_SDH_BLE_CENTRAL_LINK_COUNT;
ble_cfg.gap_cfg.role_count_cfg.central_sec_count = MIN(NRF_SDH_BLE_CENTRAL_LINK_COUNT,
BLE_GAP_ROLE_COUNT_CENTRAL_SEC_DEFAULT);
#endif
ret_code = sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &ble_cfg, *p_ram_start);
if (ret_code != NRF_SUCCESS)
{
NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_GAP_CFG_ROLE_COUNT.",
nrf_strerror_get(ret_code));
}
// Configure the maximum ATT MTU.
#if (NRF_SDH_BLE_GATT_MAX_MTU_SIZE != 23)
memset(&ble_cfg, 0x00, sizeof(ble_cfg));
ble_cfg.conn_cfg.conn_cfg_tag = conn_cfg_tag;
ble_cfg.conn_cfg.params.gatt_conn_cfg.att_mtu = NRF_SDH_BLE_GATT_MAX_MTU_SIZE;
ret_code = sd_ble_cfg_set(BLE_CONN_CFG_GATT, &ble_cfg, *p_ram_start);
if (ret_code != NRF_SUCCESS)
{
NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_CONN_CFG_GATT.",
nrf_strerror_get(ret_code));
}
#endif // NRF_SDH_BLE_GATT_MAX_MTU_SIZE != 23
#endif // NRF_SDH_BLE_TOTAL_LINK_COUNT != 0
// Configure number of custom UUIDS.
memset(&ble_cfg, 0, sizeof(ble_cfg));
ble_cfg.common_cfg.vs_uuid_cfg.vs_uuid_count = NRF_SDH_BLE_VS_UUID_COUNT;
ret_code = sd_ble_cfg_set(BLE_COMMON_CFG_VS_UUID, &ble_cfg, *p_ram_start);
if (ret_code != NRF_SUCCESS)
{
NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_COMMON_CFG_VS_UUID.",
nrf_strerror_get(ret_code));
}
// Configure the GATTS attribute table.
memset(&ble_cfg, 0x00, sizeof(ble_cfg));
ble_cfg.gatts_cfg.attr_tab_size.attr_tab_size = NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE;
ret_code = sd_ble_cfg_set(BLE_GATTS_CFG_ATTR_TAB_SIZE, &ble_cfg, *p_ram_start);
if (ret_code != NRF_SUCCESS)
{
NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_GATTS_CFG_ATTR_TAB_SIZE.",
nrf_strerror_get(ret_code));
}
// Configure Service Changed characteristic.
memset(&ble_cfg, 0x00, sizeof(ble_cfg));
ble_cfg.gatts_cfg.service_changed.service_changed = NRF_SDH_BLE_SERVICE_CHANGED;
ret_code = sd_ble_cfg_set(BLE_GATTS_CFG_SERVICE_CHANGED, &ble_cfg, *p_ram_start);
if (ret_code != NRF_SUCCESS)
{
NRF_LOG_ERROR("sd_ble_cfg_set() returned %s when attempting to set BLE_GATTS_CFG_SERVICE_CHANGED.",
nrf_strerror_get(ret_code));
}
return NRF_SUCCESS;
}
/**@brief Function for finding the end address of the RAM. */
static uint32_t ram_end_address_get(void)
{
uint32_t ram_total_size;
#ifdef NRF51
uint32_t block_size = NRF_FICR->SIZERAMBLOCKS;
ram_total_size = block_size * NRF_FICR->NUMRAMBLOCK;
#else
ram_total_size = NRF_FICR->INFO.RAM * 1024;
#endif
return RAM_START + ram_total_size;
}
ret_code_t nrf_sdh_ble_enable(uint32_t * const p_app_ram_start)
{
// Start of RAM, obtained from linker symbol.
uint32_t const app_ram_start_link = *p_app_ram_start;
ret_code_t ret_code = sd_ble_enable(p_app_ram_start);
if (*p_app_ram_start > app_ram_start_link)
{
NRF_LOG_WARNING("Insufficient RAM allocated for the SoftDevice.");
NRF_LOG_WARNING("Change the RAM start location from 0x%x to 0x%x.",
app_ram_start_link, *p_app_ram_start);
NRF_LOG_WARNING("Maximum RAM size for application is 0x%x.",
ram_end_address_get() - (*p_app_ram_start));
}
else
{
NRF_LOG_DEBUG("RAM starts at 0x%x", app_ram_start_link);
if (*p_app_ram_start != app_ram_start_link)
{
NRF_LOG_DEBUG("RAM start location can be adjusted to 0x%x.", *p_app_ram_start);
NRF_LOG_DEBUG("RAM size for application can be adjusted to 0x%x.",
ram_end_address_get() - (*p_app_ram_start));
}
}
if (ret_code == NRF_SUCCESS)
{
m_stack_is_enabled = true;
}
else
{
NRF_LOG_ERROR("sd_ble_enable() returned %s.", nrf_strerror_get(ret_code));
}
return ret_code;
}
/**@brief Function for polling BLE events.
*
* @param[in] p_context Context of the observer.
*/
static void nrf_sdh_ble_evts_poll(void * p_context)
{
UNUSED_VARIABLE(p_context);
ret_code_t ret_code;
if (!m_stack_is_enabled)
{
return;
}
while (true)
{
/*lint -save -e(587) */
__ALIGN(4) uint8_t evt_buffer[NRF_SDH_BLE_EVT_BUF_SIZE];
/*lint -restore */
ble_evt_t * p_ble_evt;
uint16_t evt_len = (uint16_t)sizeof(evt_buffer);
ret_code = sd_ble_evt_get(evt_buffer, &evt_len);
if (ret_code != NRF_SUCCESS)
{
break;
}
p_ble_evt = (ble_evt_t *)evt_buffer;
NRF_LOG_DEBUG("BLE event: 0x%x.", p_ble_evt->header.evt_id);
// Forward the event to BLE observers.
nrf_section_iter_t iter;
for (nrf_section_iter_init(&iter, &sdh_ble_observers);
nrf_section_iter_get(&iter) != NULL;
nrf_section_iter_next(&iter))
{
nrf_sdh_ble_evt_observer_t * p_observer;
nrf_sdh_ble_evt_handler_t handler;
p_observer = (nrf_sdh_ble_evt_observer_t *)nrf_section_iter_get(&iter);
handler = p_observer->handler;
handler(p_ble_evt, p_observer->p_context);
}
}
if (ret_code != NRF_ERROR_NOT_FOUND)
{
APP_ERROR_HANDLER(ret_code);
}
}
NRF_SDH_STACK_OBSERVER(m_nrf_sdh_ble_evts_poll, NRF_SDH_BLE_STACK_OBSERVER_PRIO) =
{
.handler = nrf_sdh_ble_evts_poll,
.p_context = NULL,
};
#endif // NRF_MODULE_ENABLED(NRF_SDH_BLE)

View File

@ -0,0 +1,184 @@
/**
* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**@file
*
* @defgroup nrf_sdh_ble BLE support in SoftDevice Handler
* @{
* @ingroup nrf_sdh
* @brief This file contains the declarations of types and functions required for BLE stack
* support.
*/
#ifndef NRF_SDH_BLE_H__
#define NRF_SDH_BLE_H__
#include "app_util.h"
#include "nrf_ble.h"
#include "nrf_section_iter.h"
#include "sdk_config.h"
#include "sdk_errors.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Size of the buffer for a BLE event. */
#define NRF_SDH_BLE_EVT_BUF_SIZE BLE_EVT_LEN_MAX(NRF_SDH_BLE_GATT_MAX_MTU_SIZE)
#if !(defined(__LINT__))
/**@brief Macro for registering @ref nrf_sdh_soc_evt_observer_t. Modules that want to be
* notified about SoC events must register the handler using this macro.
*
* @details This macro places the observer in a section named "sdh_soc_observers".
*
* @param[in] _name Observer name.
* @param[in] _prio Priority of the observer event handler.
* The smaller the number, the higher the priority.
* @param[in] _handler BLE event handler.
* @param[in] _context Parameter to the event handler.
* @hideinitializer
*/
#define NRF_SDH_BLE_OBSERVER(_name, _prio, _handler, _context) \
STATIC_ASSERT(NRF_SDH_BLE_ENABLED, "NRF_SDH_BLE_ENABLED not set!"); \
STATIC_ASSERT(_prio < NRF_SDH_BLE_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \
NRF_SECTION_SET_ITEM_REGISTER(sdh_ble_observers, _prio, static nrf_sdh_ble_evt_observer_t _name) = \
{ \
.handler = _handler, \
.p_context = _context \
}
/**@brief Macro for registering an array of @ref nrf_sdh_ble_evt_observer_t.
* Modules that want to be notified about SoC events must register the handler using
* this macro.
*
* Each observer's handler will be dispatched an event with its relative context from @p _context.
* This macro places the observer in a section named "sdh_ble_observers".
*
* @param[in] _name Observer name.
* @param[in] _prio Priority of the observer event handler.
* The smaller the number, the higher the priority.
* @param[in] _handler BLE event handler.
* @param[in] _context An array of parameters to the event handler.
* @param[in] _cnt Number of observers to register.
* @hideinitializer
*/
#define NRF_SDH_BLE_OBSERVERS(_name, _prio, _handler, _context, _cnt) \
STATIC_ASSERT(NRF_SDH_BLE_ENABLED, "NRF_SDH_BLE_ENABLED not set!"); \
STATIC_ASSERT(_prio < NRF_SDH_BLE_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \
NRF_SECTION_SET_ITEM_REGISTER(sdh_ble_observers, _prio, static nrf_sdh_ble_evt_observer_t _name[_cnt]) = \
{ \
MACRO_REPEAT_FOR(_cnt, HANDLER_SET, _handler, _context) \
}
#if !(defined(DOXYGEN))
#define HANDLER_SET(_idx, _handler, _context) \
{ \
.handler = _handler, \
.p_context = _context[_idx], \
},
#endif
#else // __LINT__
/* Swallow semicolons */
/*lint -save -esym(528, *) -esym(529, *) : Symbol not referenced. */
#define NRF_SDH_BLE_OBSERVER(A, B, C, D) static int semicolon_swallow_##A
#define NRF_SDH_BLE_OBSERVERS(A, B, C, D, E) static int semicolon_swallow_##A
/*lint -restore */
#endif
/**@brief BLE stack event handler. */
typedef void (*nrf_sdh_ble_evt_handler_t)(ble_evt_t const * p_ble_evt, void * p_context);
/**@brief BLE event observer. */
typedef struct
{
nrf_sdh_ble_evt_handler_t handler; //!< BLE event handler.
void * p_context; //!< A parameter to the event handler.
} const nrf_sdh_ble_evt_observer_t;
/**@brief Function for retrieving the address of the start of application's RAM.
*
* @param[out] p_app_ram_start Address of the start of application's RAM.
*
* @retval NRF_SUCCESS If the address was successfully retrieved.
* @retval NRF_ERROR_NULL If @p p_app_ram_start was @c NULL.
*/
ret_code_t nrf_sdh_ble_app_ram_start_get(uint32_t * p_app_ram_start);
/**@brief Set the default BLE stack configuration.
*
* This function configures the BLE stack with the settings specified in the
* SoftDevice handler BLE configuration. The following configurations will be set:
* - Number of peripheral links
* - Number of central links
* - ATT MTU size (for the given connection)
* - Vendor specific UUID count
* - GATTS Attribute table size
* - Service changed
*
* @param[in] conn_cfg_tag The connection to configure.
* @param[out] p_ram_start Application RAM start address.
*/
ret_code_t nrf_sdh_ble_default_cfg_set(uint8_t conn_cfg_tag, uint32_t * p_ram_start);
/**@brief Function for configuring and enabling the BLE stack.
*
* @param[in] p_app_ram_start Address of the start of application's RAM.
*/
ret_code_t nrf_sdh_ble_enable(uint32_t * p_app_ram_start);
#ifdef __cplusplus
}
#endif
#endif // NRF_SDH_BLE_H__
/** @} */

View File

@ -0,0 +1,118 @@
/**
* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_SDH_SOC)
#include "nrf_sdh_soc.h"
#include "nrf_sdh.h"
#include "nrf_soc.h"
#include "app_error.h"
#define NRF_LOG_MODULE_NAME nrf_sdh_soc
#if NRF_SDH_SOC_LOG_ENABLED
#define NRF_LOG_LEVEL NRF_SDH_SOC_LOG_LEVEL
#define NRF_LOG_INFO_COLOR NRF_SDH_SOC_INFO_COLOR
#define NRF_LOG_DEBUG_COLOR NRF_SDH_SOC_DEBUG_COLOR
#else
#define NRF_LOG_LEVEL 0
#endif // NRF_SDH_SOC_LOG_ENABLED
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
// Create section set "sdh_soc_observers".
NRF_SECTION_SET_DEF(sdh_soc_observers, nrf_sdh_soc_evt_observer_t, NRF_SDH_SOC_OBSERVER_PRIO_LEVELS);
/**@brief Function for polling SoC events.
*
* @param[in] p_context Context of the observer.
*/
static void nrf_sdh_soc_evts_poll(void * p_context)
{
ret_code_t ret_code;
UNUSED_VARIABLE(p_context);
while (true)
{
uint32_t evt_id;
ret_code = sd_evt_get(&evt_id);
if (ret_code != NRF_SUCCESS)
{
break;
}
NRF_LOG_DEBUG("SoC event: 0x%x.", evt_id);
// Forward the event to SoC observers.
nrf_section_iter_t iter;
for (nrf_section_iter_init(&iter, &sdh_soc_observers);
nrf_section_iter_get(&iter) != NULL;
nrf_section_iter_next(&iter))
{
nrf_sdh_soc_evt_observer_t * p_observer;
nrf_sdh_soc_evt_handler_t handler;
p_observer = (nrf_sdh_soc_evt_observer_t *) nrf_section_iter_get(&iter);
handler = p_observer->handler;
handler(evt_id, p_observer->p_context);
}
}
if (ret_code != NRF_ERROR_NOT_FOUND)
{
APP_ERROR_HANDLER(ret_code);
}
}
NRF_SDH_STACK_OBSERVER(m_nrf_sdh_soc_evts_poll, NRF_SDH_SOC_STACK_OBSERVER_PRIO) =
{
.handler = nrf_sdh_soc_evts_poll,
.p_context = NULL,
};
#endif // NRF_MODULE_ENABLED(NRF_SDH_SOC)

View File

@ -0,0 +1,143 @@
/**
* Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**@file
*
* @defgroup nrf_sdh_soc SoC support in SoftDevice Handler
* @{
* @ingroup nrf_sdh
* @brief This file contains the declarations of types and functions required for SoftDevice Handler
* SoC support.
*/
#ifndef NRF_SDH_SOC_H__
#define NRF_SDH_SOC_H__
#include "sdk_common.h"
#include "nrf_section_iter.h"
#include "nrf_soc.h"
#ifdef __cplusplus
extern "C" {
#endif
#if !(defined(__LINT__))
/**@brief Macro for registering @ref nrf_sdh_soc_evt_observer_t. Modules that want to be
* notified about SoC events must register the handler using this macro.
*
* @details This macro places the observer in a section named "sdh_soc_observers".
*
* @param[in] _name Observer name.
* @param[in] _prio Priority of the observer event handler.
* The smaller the number, the higher the priority.
* @param[in] _handler SoC event handler.
* @param[in] _context Parameter to the event handler.
* @hideinitializer
*/
#define NRF_SDH_SOC_OBSERVER(_name, _prio, _handler, _context) \
STATIC_ASSERT(NRF_SDH_SOC_ENABLED, "NRF_SDH_SOC_ENABLED not set!"); \
STATIC_ASSERT(_prio < NRF_SDH_SOC_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \
NRF_SECTION_SET_ITEM_REGISTER(sdh_soc_observers, _prio, static nrf_sdh_soc_evt_observer_t _name) = \
{ \
.handler = _handler, \
.p_context = _context \
}
/**@brief Macro for registering an array of @ref nrf_sdh_soc_evt_observer_t.
* Modules that want to be notified about SoC events must register the handler using
* this macro.
*
* Each observer's handler will be dispatched an event with its relative context from @p _context.
* This macro places the observer in a section named "sdh_soc_observers".
*
* @param[in] _name Observer name.
* @param[in] _prio Priority of the observer event handler.
* The smaller the number, the higher the priority.
* @param[in] _handler SoC event handler.
* @param[in] _context An array of parameters to the event handler.
* @param[in] _cnt Number of observers to register.
* @hideinitializer
*/
#define NRF_SDH_SOC_EVENT_OBSERVERS(_name, _prio, _handler, _context, _cnt) \
STATIC_ASSERT(NRF_SDH_SOC_ENABLED, "NRF_SDH_SOC_ENABLED not set!"); \
STATIC_ASSERT(_prio < NRF_SDH_SOC_OBSERVER_PRIO_LEVELS, "Priority level unavailable."); \
NRF_SECTION_SET_ITEM_REGISTER(sdh_soc_observers, _prio, static nrf_sdh_soc_evt_observer_t _name[_cnt]) = \
{ \
MACRO_REPEAT_FOR(_cnt, HANDLER_SET, _handler, _context) \
}
#if !(defined(DOXYGEN))
#define HANDLER_SET(_idx, _handler, _context) \
{ \
.handler = _handler, \
.p_context = _context[_idx], \
},
#endif
#else // __LINT__
/* Swallow semicolons */
/*lint -save -esym(528, *) -esym(529, *) : Symbol not referenced. */
#define NRF_SDH_SOC_OBSERVER(A, B, C, D) static int semicolon_swallow_##A
#define NRF_SDH_SOC_OBSERVERS(A, B, C, D, E) static int semicolon_swallow_##A
/*lint -restore */
#endif
/**@brief SoC event handler. */
typedef void (*nrf_sdh_soc_evt_handler_t) (uint32_t evt_id, void * p_context);
/**@brief SoC event observer. */
typedef struct
{
nrf_sdh_soc_evt_handler_t handler; //!< SoC event handler.
void * p_context; //!< A parameter to the event handler.
} const nrf_sdh_soc_evt_observer_t;
#ifdef __cplusplus
}
#endif
#endif // NRF_SDH_SOC_H__
/** @} */

View File

@ -0,0 +1,38 @@
{
"name": "softdevice",
"macros": [
"SOFTDEVICE_PRESENT=1",
"S140",
"BLE_STACK_SUPPORT_REQD",
"NRF_SDH_CLOCK_LF_SRC=1",
"NRF_SDH_CLOCK_LF_RC_CTIV=0",
"NRF_SDH_CLOCK_LF_RC_TEMP_CTIV=0",
"NRF_SDH_CLOCK_LF_XTAL_ACCURACY=7",
"NRF_SD_BLE_API_VERSION=5",
"NRF_SDH_ENABLED=1",
"NRF_SDH_BLE_ENABLED=1",
"PEER_MANAGER_ENABLED=1",
"NRF_SDH_BLE_GATT_MAX_MTU_SIZE=23",
"NRF_SDH_BLE_OBSERVER_PRIO_LEVELS=4",
"NRF_SDH_BLE_GAP_EVENT_LENGTH=3",
"BLE_ADV_BLE_OBSERVER_PRIO=1",
"BLE_CONN_STATE_BLE_OBSERVER_PRIO=0",
"BLE_CONN_PARAMS_BLE_OBSERVER_PRIO=1",
"NRF_BLE_GATT_BLE_OBSERVER_PRIO=1",
"NRF_SDH_DISPATCH_MODEL=2",
"NRF_SDH_SOC_ENABLED=1",
"NRF_SDH_STACK_OBSERVER_PRIO_LEVELS=2",
"NRF_SDH_STATE_OBSERVER_PRIO_LEVELS=2",
"NRF_SDH_SOC_OBSERVER_PRIO_LEVELS=2",
"NRF_SDH_REQ_OBSERVER_PRIO_LEVELS=2",
"NRF_SDH_BLE_STACK_OBSERVER_PRIO=0",
"NRF_SDH_SOC_STACK_OBSERVER_PRIO=0",
"FDS_BACKEND=2",
"SWI_DISABLE1=1"
],
"target_overrides": {
"*": {
"target.bootloader_img": "hex/s140_nrf52_6.0.0_softdevice.hex"
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,700 @@
/**
* Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef FDS_H__
#define FDS_H__
/**
* @defgroup fds Flash Data Storage
* @ingroup app_common
* @{
*
* @brief Flash Data Storage (FDS).
*
* @details Flash Data Storage is a minimalistic, record-oriented file system for the on-chip
* flash. Files are stored as a collection of records of variable length. FDS supports
* synchronous read operations and asynchronous write operations (write, update,
* and delete). FDS can be used from multiple threads.
*/
#include <stdint.h>
#include <stdbool.h>
#include "sdk_errors.h"
#include "app_util_platform.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@brief Invalid file ID.
*
* This value must not be used as a file ID by the application.
*/
#define FDS_FILE_ID_INVALID (0xFFFF)
/**@brief Record key for deleted records.
*
* This key is used to flag a record as "dirty", which means that it should be removed during
* the next garbage collection. This value must not be used as a record key by the application.
*/
#define FDS_RECORD_KEY_DIRTY (0x0000)
/**@brief FDS return values.
*/
enum
{
FDS_SUCCESS = NRF_SUCCESS, //!< The operation completed successfully.
FDS_ERR_OPERATION_TIMEOUT, //!< Error. The operation timed out.
FDS_ERR_NOT_INITIALIZED, //!< Error. The module has not been initialized.
FDS_ERR_UNALIGNED_ADDR, //!< Error. The input data is not aligned to a word boundary.
FDS_ERR_INVALID_ARG, //!< Error. The parameter contains invalid data.
FDS_ERR_NULL_ARG, //!< Error. The parameter is NULL.
FDS_ERR_NO_OPEN_RECORDS, //!< Error. The record is not open, so it cannot be closed.
FDS_ERR_NO_SPACE_IN_FLASH, //!< Error. There is no space in flash memory.
FDS_ERR_NO_SPACE_IN_QUEUES, //!< Error. There is no space in the internal queues.
FDS_ERR_RECORD_TOO_LARGE, //!< Error. The record exceeds the maximum allowed size.
FDS_ERR_NOT_FOUND, //!< Error. The record was not found.
FDS_ERR_NO_PAGES, //!< Error. No flash pages are available.
FDS_ERR_USER_LIMIT_REACHED, //!< Error. The maximum number of users has been reached.
FDS_ERR_CRC_CHECK_FAILED, //!< Error. The CRC check failed.
FDS_ERR_BUSY, //!< Error. The underlying flash subsystem was busy.
FDS_ERR_INTERNAL, //!< Error. An internal error occurred.
};
/**@brief The record metadata as stored in flash.
* @warning Do not edit or reorder the fields in this structure.
*/
typedef struct
{
uint16_t record_key; //!< The record key.
uint16_t length_words; //!< The length of the record data (in 4-byte words).
uint16_t file_id; //!< The ID of the file that the record belongs to.
uint16_t crc16; //!< CRC16-CCITT check value.
/* The CRC is calculated over the entire record as stored in flash,
* including the record metadata except the CRC field itself.
*/
uint32_t record_id; //!< The unique record ID (32 bits).
} fds_header_t;
/**@brief The record descriptor structure that is used to manipulate records.
*
* This structure is used by the FDS module. You must provide the descriptor to the module when
* you manipulate existing records. However, you should never modify it or use any of its fields.
*
* @note Never reuse the same descriptor for different records.
*/
typedef struct
{
uint32_t record_id; //!< The unique record ID.
uint32_t const * p_record; //!< The last known location of the record in flash.
uint16_t gc_run_count; //!< Number of times garbage collection has been run.
bool record_is_open; //!< Whether the record is currently open.
} fds_record_desc_t;
/**@brief Structure that can be used to read the contents of a record stored in flash.
*
* This structure does not reflect the physical layout of a record in flash, but it points
* to the locations where the record header (metadata) and the record data are stored.
*/
typedef struct
{
fds_header_t const * p_header; //!< Location of the record header in flash.
void const * p_data; //!< Location of the record data in flash.
} fds_flash_record_t;
/**@brief A record to be written to flash. */
typedef struct
{
uint16_t file_id; //!< The ID of the file that the record belongs to.
uint16_t key; //!< The record key.
struct
{
void const * p_data;
uint32_t length_words;
} data;
} fds_record_t;
/**@brief A token to a reserved space in flash, created by @ref fds_reserve.
*
* This token can be used to write the record in the reserved space (@ref fds_record_write_reserved)
* or to cancel the reservation (@ref fds_reserve_cancel).
*/
typedef struct
{
uint16_t page; //!< The logical ID of the page where space was reserved.
uint16_t length_words; //!< The amount of space reserved (in 4-byte words).
} fds_reserve_token_t;
/**@brief A token to keep information about the progress of @ref fds_record_find,
* @ref fds_record_find_by_key, and @ref fds_record_find_in_file.
*
* @note Always zero-initialize the token before using it for the first time.
* @note Never reuse the same token to search for different records.
*/
typedef struct
{
uint32_t const * p_addr;
uint16_t page;
} fds_find_token_t;
/**@brief FDS event IDs.
*/
typedef enum
{
FDS_EVT_INIT, //!< Event for @ref fds_init.
FDS_EVT_WRITE, //!< Event for @ref fds_record_write and @ref fds_record_write_reserved.
FDS_EVT_UPDATE, //!< Event for @ref fds_record_update.
FDS_EVT_DEL_RECORD, //!< Event for @ref fds_record_delete.
FDS_EVT_DEL_FILE, //!< Event for @ref fds_file_delete.
FDS_EVT_GC //!< Event for @ref fds_gc.
} fds_evt_id_t;
ANON_UNIONS_ENABLE;
/**@brief An FDS event. */
typedef struct
{
fds_evt_id_t id; //!< The event ID. See @ref fds_evt_id_t.
ret_code_t result; //!< The result of the operation related to this event.
union
{
struct
{
uint32_t record_id;
uint16_t file_id;
uint16_t record_key;
bool is_record_updated;
} write; //!< Information for @ref FDS_EVT_WRITE and @ref FDS_EVT_UPDATE events.
struct
{
uint32_t record_id;
uint16_t file_id;
uint16_t record_key;
} del; //!< Information for @ref FDS_EVT_DEL_RECORD and @ref FDS_EVT_DEL_FILE events.
};
} fds_evt_t;
ANON_UNIONS_DISABLE;
/**@brief File system statistics. */
typedef struct
{
uint16_t pages_available; //!< The number of pages available.
uint16_t open_records; //!< The number of open records.
uint16_t valid_records; //!< The number of valid records.
uint16_t dirty_records; //!< The number of deleted ("dirty") records.
uint16_t words_reserved; //!< The number of words reserved by @ref fds_reserve().
/**@brief The number of words written to flash, including those reserved for future writes. */
uint16_t words_used;
/**@brief The largest number of free contiguous words in the file system.
*
* This number indicates the largest record that can be stored by FDS.
* It takes into account all reservations for future writes.
*/
uint16_t largest_contig;
/**@brief The largest number of words that can be reclaimed by garbage collection.
*
* The actual amount of space freed by garbage collection might be less than this value if
* records are open while garbage collection is run.
*/
uint16_t freeable_words;
/**@brief Filesystem corruption has been detected.
*
* One or more corrupted records were detected. FDS will heal the filesystem automatically
* next time garbage collection is run, but some data may be lost.
*
* @note: This flag is unrelated to CRC failures.
*/
bool corruption;
} fds_stat_t;
/**@brief FDS event handler function prototype.
*
* @param p_evt The event.
*/
typedef void (*fds_cb_t)(fds_evt_t const * p_evt);
/**@brief Function for registering an FDS event handler.
*
* The maximum amount of handlers that can be registered can be configured by changing the value
* of @ref FDS_MAX_USERS in fds_config.h.
*
* @param[in] cb The event handler function.
*
* @retval FDS_SUCCESS If the event handler was registered successfully.
* @retval FDS_ERR_USER_LIMIT_REACHED If the maximum number of registered callbacks is reached.
*/
ret_code_t fds_register(fds_cb_t cb);
/**@brief Function for initializing the module.
*
* This function initializes the module and installs the file system (unless it is installed
* already).
*
* This function is asynchronous. Completion is reported through an event. Make sure to call
* @ref fds_register before calling @ref fds_init so that you receive the completion event.
*
* @retval FDS_SUCCESS If the operation was queued successfully.
* @retval FDS_ERR_NO_PAGES If there is no space available in flash memory to install the
* file system.
*/
ret_code_t fds_init(void);
/**@brief Function for writing a record to flash.
*
* There are no restrictions on the file ID and the record key, except that the record key must be
* different from @ref FDS_RECORD_KEY_DIRTY and the file ID must be different from
* @ref FDS_FILE_ID_INVALID. In particular, no restrictions are made regarding the uniqueness of
* the file ID or the record key. All records with the same file ID are grouped into one file.
* If no file with the specified ID exists, it is created. There can be multiple records with the
* same record key in a file.
*
* Some modules need exclusive use of certain file IDs and record keys.
* See @ref lib_fds_functionality_keys for details.
*
* Record data can consist of multiple chunks. The data must be aligned to a 4 byte boundary, and
* because it is not buffered internally, it must be kept in memory until the callback for the
* operation has been received. The length of the data must not exceed @ref FDS_VIRTUAL_PAGE_SIZE
* words minus 14 bytes.
*
* This function is asynchronous. Completion is reported through an event that is sent to
* the registered event handler function.
*
* @param[out] p_desc The descriptor of the record that was written. Pass NULL if you do not
* need the descriptor.
* @param[in] p_record The record to be written to flash.
*
* @retval FDS_SUCCESS If the operation was queued successfully.
* @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized.
* @retval FDS_ERR_NULL_ARG If @p p_record is NULL.
* @retval FDS_ERR_INVALID_ARG If the file ID or the record key is invalid.
* @retval FDS_ERR_UNALIGNED_ADDR If the record data is not aligned to a 4 byte boundary.
* @retval FDS_ERR_RECORD_TOO_LARGE If the record data exceeds the maximum length.
* @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full or there are more record
* chunks than can be buffered.
* @retval FDS_ERR_NO_SPACE_IN_FLASH If there is not enough free space in flash to store the
* record.
*/
ret_code_t fds_record_write(fds_record_desc_t * p_desc,
fds_record_t const * p_record);
/**@brief Function for reserving space in flash.
*
* This function can be used to reserve space in flash memory. To write a record into the reserved
* space, use @ref fds_record_write_reserved. Alternatively, use @ref fds_reserve_cancel to cancel
* a reservation.
*
* Note that this function does not write any data to flash.
*
* @param[out] p_token A token that can be used to write a record in the reserved space or
* cancel the reservation.
* @param[in] length_words The length of the record data (in 4-byte words).
*
* @retval FDS_SUCCESS If the flash space was reserved successfully.
* @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized.
* @retval FDS_ERR_NULL_ARG If @p p_token is NULL instead of a valid token address.
* @retval FDS_ERR_RECORD_TOO_LARGE If the record length exceeds the maximum length.
* @retval FDS_ERR_NO_SPACE_IN_FLASH If there is not enough free space in flash to store the
* record.
*/
ret_code_t fds_reserve(fds_reserve_token_t * p_token, uint16_t length_words);
/**@brief Function for canceling an @ref fds_reserve operation.
*
* @param[in] p_token The token that identifies the reservation, produced by @ref fds_reserve.
*
* @retval FDS_SUCCESS If the reservation was canceled.
* @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized.
* @retval FDS_ERR_NULL_ARG If @p p_token is NULL instead of a valid token address.
* @retval FDS_ERR_INVALID_ARG If @p p_token contains invalid data.
*/
ret_code_t fds_reserve_cancel(fds_reserve_token_t * p_token);
/**@brief Function for writing a record to a space in flash that was reserved using
* @ref fds_reserve.
*
* There are no restrictions on the file ID and the record key, except that the record key must be
* different from @ref FDS_RECORD_KEY_DIRTY and the file ID must be different from
* @ref FDS_FILE_ID_INVALID. In particular, no restrictions are made regarding the uniqueness of
* the file ID or the record key. All records with the same file ID are grouped into one file.
* If no file with the specified ID exists, it is created. There can be multiple records with the
* same record key in a file.
*
* Record data can consist of multiple chunks. The data must be aligned to a 4 byte boundary, and
* because it is not buffered internally, it must be kept in memory until the callback for the
* operation has been received. The length of the data must not exceed @ref FDS_VIRTUAL_PAGE_SIZE
* words minus 14 bytes.
*
* This function is asynchronous. Completion is reported through an event that is sent to the
* registered event handler function.
*
* @note
* This function behaves similarly to @ref fds_record_write, with the exception that it never
* fails with the error @ref FDS_ERR_NO_SPACE_IN_FLASH.
*
* @param[out] p_desc The descriptor of the record that was written. Pass NULL if you do not
* need the descriptor.
* @param[in] p_record The record to be written to flash.
* @param[in] p_token The token that identifies the space reserved in flash.
*
* @retval FDS_SUCCESS If the operation was queued successfully.
* @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized.
* @retval FDS_ERR_NULL_ARG If @p p_token is NULL instead of a valid token address.
* @retval FDS_ERR_INVALID_ARG If the file ID or the record key is invalid.
* @retval FDS_ERR_UNALIGNED_ADDR If the record data is not aligned to a 4 byte boundary.
* @retval FDS_ERR_RECORD_TOO_LARGE If the record data exceeds the maximum length.
* @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full or there are more record
* chunks than can be buffered.
*/
ret_code_t fds_record_write_reserved(fds_record_desc_t * p_desc,
fds_record_t const * p_record,
fds_reserve_token_t const * p_token);
/**@brief Function for deleting a record.
*
* Deleted records cannot be located using @ref fds_record_find, @ref fds_record_find_by_key, or
* @ref fds_record_find_in_file. Additionally, they can no longer be opened using
* @ref fds_record_open.
*
* Note that deleting a record does not free the space it occupies in flash memory.
* To reclaim flash space used by deleted records, call @ref fds_gc to run garbage collection.
*
* This function is asynchronous. Completion is reported through an event that is sent to the
* registered event handler function.
*
* @param[in] p_desc The descriptor of the record that should be deleted.
*
* @retval FDS_SUCCESS If the operation was queued successfully.
* @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized.
* @retval FDS_ERR_NULL_ARG If the specified record descriptor @p p_desc is NULL.
* @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full.
*/
ret_code_t fds_record_delete(fds_record_desc_t * p_desc);
/**@brief Function for deleting all records in a file.
*
* This function deletes a file, including all its records. Deleted records cannot be located
* using @ref fds_record_find, @ref fds_record_find_by_key, or @ref fds_record_find_in_file.
* Additionally, they can no longer be opened using @ref fds_record_open.
*
* Note that deleting records does not free the space they occupy in flash memory.
* To reclaim flash space used by deleted records, call @ref fds_gc to run garbage collection.
*
* This function is asynchronous. Completion is reported through an event that is sent to the
* registered event handler function.
*
* @param[in] file_id The ID of the file to be deleted.
*
* @retval FDS_SUCCESS If the operation was queued successfully.
* @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized.
* @retval FDS_ERR_INVALID_ARG If the specified @p file_id is invalid.
* @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full.
*/
ret_code_t fds_file_delete(uint16_t file_id);
/**@brief Function for updating a record.
*
* Updating a record first writes a new record (@p p_record) to flash and then deletes the
* old record (identified by @p p_desc).
*
* There are no restrictions on the file ID and the record key, except that the record key must be
* different from @ref FDS_RECORD_KEY_DIRTY and the file ID must be different from
* @ref FDS_FILE_ID_INVALID. In particular, no restrictions are made regarding the uniqueness of
* the file ID or the record key. All records with the same file ID are grouped into one file.
* If no file with the specified ID exists, it is created. There can be multiple records with the
* same record key in a file.
*
* Record data can consist of multiple chunks. The data must be aligned to a 4 byte boundary, and
* because it is not buffered internally, it must be kept in memory until the callback for the
* operation has been received. The length of the data must not exceed @ref FDS_VIRTUAL_PAGE_SIZE
* words minus 14 bytes.
*
* This function is asynchronous. Completion is reported through an event that is sent to the
* registered event handler function.
*
* @param[in, out] p_desc The descriptor of the record to update. When the function
* returns with FDS_SUCCESS, this parameter contains the
* descriptor of the newly written record.
* @param[in] p_record The updated record to be written to flash.
*
* @retval FDS_SUCCESS If the operation was queued successfully.
* @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized.
* @retval FDS_ERR_INVALID_ARG If the file ID or the record key is invalid.
* @retval FDS_ERR_UNALIGNED_ADDR If the record data is not aligned to a 4 byte boundary.
* @retval FDS_ERR_RECORD_TOO_LARGE If the record data exceeds the maximum length.
* @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full or there are more record
* chunks than can be buffered.
* @retval FDS_ERR_NO_SPACE_IN_FLASH If there is not enough free space in flash to store the
* updated record.
*/
ret_code_t fds_record_update(fds_record_desc_t * p_desc,
fds_record_t const * p_record);
/**@brief Function for iterating through all records in flash.
*
* To search for the next record, call the function again and supply the same @ref fds_find_token_t
* structure to resume searching from the last record that was found.
*
* Note that the order with which records are iterated is not defined.
*
* @param[out] p_desc The descriptor of the record that was found.
* @param[out] p_token A token containing information about the progress of the operation.
*
* @retval FDS_SUCCESS If a record was found.
* @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized.
* @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_token is NULL.
* @retval FDS_ERR_NOT_FOUND If no matching record was found.
*/
ret_code_t fds_record_iterate(fds_record_desc_t * p_desc,
fds_find_token_t * p_token);
/**@brief Function for searching for records with a given record key in a file.
*
* This function finds the first record in a file that has the given record key. To search for the
* next record with the same key in the file, call the function again and supply the same
* @ref fds_find_token_t structure to resume searching from the last record that was found.
*
* @param[in] file_id The file ID.
* @param[in] record_key The record key.
* @param[out] p_desc The descriptor of the record that was found.
* @param[out] p_token A token containing information about the progress of the operation.
*
* @retval FDS_SUCCESS If a record was found.
* @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized.
* @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_token is NULL.
* @retval FDS_ERR_NOT_FOUND If no matching record was found.
*/
ret_code_t fds_record_find(uint16_t file_id,
uint16_t record_key,
fds_record_desc_t * p_desc,
fds_find_token_t * p_token);
/**@brief Function for searching for records with a given record key.
*
* This function finds the first record with a given record key, independent of the file it
* belongs to. To search for the next record with the same key, call the function again and supply
* the same @ref fds_find_token_t structure to resume searching from the last record that was found.
*
* @param[in] record_key The record key.
* @param[out] p_desc The descriptor of the record that was found.
* @param[out] p_token A token containing information about the progress of the operation.
*
* @retval FDS_SUCCESS If a record was found.
* @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized.
* @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_token is NULL.
* @retval FDS_ERR_NOT_FOUND If no record with the given key was found.
*/
ret_code_t fds_record_find_by_key(uint16_t record_key,
fds_record_desc_t * p_desc,
fds_find_token_t * p_token);
/**@brief Function for searching for any record in a file.
*
* This function finds the first record in a file, independent of its record key.
* To search for the next record in the same file, call the function again and supply the same
* @ref fds_find_token_t structure to resume searching from the last record that was found.
*
* @param[in] file_id The file ID.
* @param[out] p_desc The descriptor of the record that was found.
* @param[out] p_token A token containing information about the progress of the operation.
*
* @retval FDS_SUCCESS If a record was found.
* @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized.
* @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_token is NULL.
* @retval FDS_ERR_NOT_FOUND If no matching record was found.
*/
ret_code_t fds_record_find_in_file(uint16_t file_id,
fds_record_desc_t * p_desc,
fds_find_token_t * p_token);
/**@brief Function for opening a record for reading.
*
* This function opens a record that is stored in flash, so that it can be read. The function
* initializes an @ref fds_flash_record_t structure, which can be used to access the record data as
* well as its associated metadata. The pointers provided in the @ref fds_flash_record_t structure
* are pointers to flash memory.
*
* Opening a record with @ref fds_record_open prevents garbage collection to run on the virtual
* flash page in which record is stored, so that the contents of the memory pointed by fields in
* @ref fds_flash_record_t are guaranteed to remain unmodified as long as the record is kept open.
*
* When you are done reading a record, call @ref fds_record_close to close it. Garbage collection
* can then reclaim space on the virtual page where the record is stored. Note that you must
* provide the same descriptor for @ref fds_record_close as you did for this function.
*
* @param[in] p_desc The descriptor of the record to open.
* @param[out] p_flash_record The record, as stored in flash.
*
* @retval FDS_SUCCESS If the record was opened successfully.
* @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_flash_record is NULL.
* @retval FDS_ERR_NOT_FOUND If the record was not found. It might have been deleted, or
* it might not have been written yet.
* @retval FDS_ERR_CRC_CHECK_FAILED If the CRC check for the record failed.
*/
ret_code_t fds_record_open(fds_record_desc_t * p_desc,
fds_flash_record_t * p_flash_record);
/**@brief Function for closing a record.
*
* Closing a record allows garbage collection to run on the virtual page in which the record is
* stored (if no other records remain open on that page). The descriptor passed as an argument
* must be the same as the one used to open the record using @ref fds_record_open.
*
* Note that closing a record does not invalidate its descriptor. You can still supply the
* descriptor to all functions that accept a record descriptor as a parameter.
*
* @param[in] p_desc The descriptor of the record to close.
*
* @retval FDS_SUCCESS If the record was closed successfully.
* @retval FDS_ERR_NULL_ARG If @p p_desc is NULL.
* @retval FDS_ERR_NO_OPEN_RECORDS If the record is not open.
* @retval FDS_ERR_NOT_FOUND If the record could not be found.
*/
ret_code_t fds_record_close(fds_record_desc_t * p_desc);
/**@brief Function for running garbage collection.
*
* Garbage collection reclaims the flash space that is occupied by records that have been deleted,
* or that failed to be completely written due to, for example, a power loss.
*
* This function is asynchronous. Completion is reported through an event that is sent to the
* registered event handler function.
*
* @retval FDS_SUCCESS If the operation was queued successfully.
* @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized.
* @retval FDS_ERR_NO_SPACE_IN_QUEUES If the operation queue is full.
*/
ret_code_t fds_gc(void);
/**@brief Function for obtaining a descriptor from a record ID.
*
* This function can be used to reconstruct a descriptor from a record ID, like the one that is
* passed to the callback function.
*
* @note
* This function does not check whether a record with the given record ID exists.
* If a non-existing record ID is supplied, the resulting descriptor is invalid and will cause
* other functions to fail when it is supplied as parameter.
*
* @param[out] p_desc The descriptor of the record with the given record ID.
* @param[in] record_id The record ID for which a descriptor should be returned.
*
* @retval FDS_SUCCESS If a descriptor was returned.
* @retval FDS_ERR_NULL_ARG If @p p_desc is NULL.
*/
ret_code_t fds_descriptor_from_rec_id(fds_record_desc_t * p_desc,
uint32_t record_id);
/**@brief Function for obtaining a record ID from a record descriptor.
*
* This function can be used to extract a record ID from a descriptor. For example, you could use
* it in the callback function to compare the record ID of an event to the record IDs of the
* records for which you have a descriptor.
*
* @warning
* This function does not check whether the record descriptor is valid. If the descriptor is not
* initialized or has been tampered with, the resulting record ID might be invalid.
*
* @param[in] p_desc The descriptor from which the record ID should be extracted.
* @param[out] p_record_id The record ID that is contained in the given descriptor.
*
* @retval FDS_SUCCESS If a record ID was returned.
* @retval FDS_ERR_NULL_ARG If @p p_desc or @p p_record_id is NULL.
*/
ret_code_t fds_record_id_from_desc(fds_record_desc_t const * p_desc,
uint32_t * p_record_id);
/**@brief Function for retrieving file system statistics.
*
* This function retrieves file system statistics, such as the number of open records, the space
* that can be reclaimed by garbage collection, and others.
*
* @param[out] p_stat File system statistics.
*
* @retval FDS_SUCCESS If the statistics were returned successfully.
* @retval FDS_ERR_NOT_INITIALIZED If the module is not initialized.
* @retval FDS_ERR_NULL_ARG If @p p_stat is NULL.
*/
ret_code_t fds_stat(fds_stat_t * p_stat);
/** @} */
#ifdef __cplusplus
}
#endif
#endif // FDS_H__

View File

@ -0,0 +1,327 @@
/**
* Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef FDS_INTERNAL_DEFS_H__
#define FDS_INTERNAL_DEFS_H__
#include "sdk_config.h"
#include <stdint.h>
#include <stdbool.h>
#if defined (FDS_THREADS)
#include "nrf_soc.h"
#include "app_util_platform.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#define FDS_PAGE_TAG_SIZE (2) // Page tag size, in 4-byte words.
#define FDS_PAGE_TAG_WORD_0 (0) // Offset of the first word in the page tag from the page address.
#define FDS_PAGE_TAG_WORD_1 (1) // Offset of the second word in the page tag from the page address.
// Page tag constants
#define FDS_PAGE_TAG_MAGIC (0xDEADC0DE)
#define FDS_PAGE_TAG_SWAP (0xF11E01FF)
#define FDS_PAGE_TAG_DATA (0xF11E01FE)
#define FDS_ERASED_WORD (0xFFFFFFFF)
#define FDS_OFFSET_TL (0) // Offset of TL from the record base address, in 4-byte words.
#define FDS_OFFSET_IC (1) // Offset of IC from the record base address, in 4-byte words.
#define FDS_OFFSET_ID (2) // Offset of ID from the record base address, in 4-byte words.
#define FDS_OFFSET_DATA (3) // Offset of the data from the record base address, in 4-byte words.
#define FDS_HEADER_SIZE_TL (1) // Size of the TL part of the header, in 4-byte words.
#define FDS_HEADER_SIZE_IC (1) // Size of the IC part of the header, in 4-byte words.
#define FDS_HEADER_SIZE_ID (1) // Size of the record ID in the header, in 4-byte words.
#define FDS_HEADER_SIZE (3) // Size of the whole header, in 4-byte words.
#define FDS_OP_EXECUTING (NRF_SUCCESS)
#define FDS_OP_COMPLETED (0x1D1D)
#define NRF_FSTORAGE_NVMC 1
#define NRF_FSTORAGE_SD 2
// The size of a physical page, in 4-byte words.
#if defined(NRF51)
#define FDS_PHY_PAGE_SIZE (256)
#else
#define FDS_PHY_PAGE_SIZE (1024)
#endif
// The number of physical pages to be used. This value is configured indirectly.
#define FDS_PHY_PAGES ((FDS_VIRTUAL_PAGES * FDS_VIRTUAL_PAGE_SIZE) / FDS_PHY_PAGE_SIZE)
// The size of a virtual page, in number of physical pages.
#define FDS_PHY_PAGES_IN_VPAGE (FDS_VIRTUAL_PAGE_SIZE / FDS_PHY_PAGE_SIZE)
// The number of pages available to store data; which is the total minus one (the swap).
#define FDS_DATA_PAGES (FDS_VIRTUAL_PAGES - 1)
// Just a shorter name for the size, in words, of a virtual page.
#define FDS_PAGE_SIZE (FDS_VIRTUAL_PAGE_SIZE)
#if (FDS_VIRTUAL_PAGE_SIZE % FDS_PHY_PAGE_SIZE != 0)
#error "FDS_VIRTUAL_PAGE_SIZE must be a multiple of the size of a physical page."
#endif
#if (FDS_VIRTUAL_PAGES < 2)
#error "FDS requires at least two virtual pages."
#endif
// Page types.
typedef enum
{
FDS_PAGE_DATA, // Page is ready for storage.
FDS_PAGE_SWAP, // Page is reserved for garbage collection.
FDS_PAGE_ERASED, // Page is erased.
FDS_PAGE_UNDEFINED, // Undefined page type.
} fds_page_type_t;
typedef enum
{
FDS_HEADER_VALID, // Valid header.
FDS_HEADER_DIRTY, // Header is incomplete, or record has been deleted.
FDS_HEADER_CORRUPT // Header contains corrupt information, not related to CRC.
} fds_header_status_t;
typedef struct
{
fds_page_type_t page_type; // The page type.
uint32_t const * p_addr; // The address of the page.
uint16_t write_offset; // The page write offset, in 4-byte words.
uint16_t words_reserved; // The amount of words reserved.
uint32_t volatile records_open; // The number of open records.
bool can_gc; // Indicates that there are some records that have been deleted.
} fds_page_t;
typedef struct
{
uint32_t const * p_addr;
uint16_t write_offset;
} fds_swap_page_t;
// FDS op-codes.
typedef enum
{
FDS_OP_NONE,
FDS_OP_INIT, // Initialize the module.
FDS_OP_WRITE, // Write a record to flash.
FDS_OP_UPDATE, // Update a record.
FDS_OP_DEL_RECORD, // Delete a record.
FDS_OP_DEL_FILE, // Delete a file.
FDS_OP_GC // Run garbage collection.
} fds_op_code_t;
typedef enum
{
FDS_OP_INIT_TAG_SWAP,
FDS_OP_INIT_TAG_DATA,
FDS_OP_INIT_ERASE_SWAP,
FDS_OP_INIT_PROMOTE_SWAP,
} fds_init_step_t;
typedef enum
{
FDS_OP_WRITE_HEADER_BEGIN, // Write the record key and length.
FDS_OP_WRITE_HEADER_FINALIZE, // Write the file ID and CRC.
FDS_OP_WRITE_RECORD_ID, // Write the record ID.
FDS_OP_WRITE_DATA, // Write the record data.
FDS_OP_WRITE_FIND_RECORD,
FDS_OP_WRITE_FLAG_DIRTY, // Flag a record as dirty (as part of an update operation).
FDS_OP_WRITE_DONE,
} fds_write_step_t;
typedef enum
{
FDS_OP_DEL_RECORD_FLAG_DIRTY, // Flag a record as dirty.
FDS_OP_DEL_FILE_FLAG_DIRTY, // Flag multiple records as dirty.
FDS_OP_DEL_DONE,
} fds_delete_step_t;
#if defined(__CC_ARM)
#pragma push
#pragma anon_unions
#elif defined(__ICCARM__)
#pragma language=extended
#elif defined(__GNUC__)
// anonymous unions are enabled by default
#endif
typedef struct
{
fds_op_code_t op_code; // The opcode for the operation.
union
{
struct
{
fds_init_step_t step; // The current step the operation is at.
} init;
struct
{
fds_header_t header;
void const * p_data;
uint16_t page; // The page the flash space for this command was reserved.
fds_write_step_t step; // The current step the operation is at.
uint32_t record_to_delete; // The record to delete in case this is an update.
} write;
struct
{
fds_delete_step_t step;
uint16_t file_id;
uint16_t record_key;
uint32_t record_to_delete;
} del;
};
} fds_op_t;
#if defined(__CC_ARM)
#pragma pop
#elif defined(__ICCARM__)
// leave anonymous unions enabled
#elif defined(__GNUC__)
// anonymous unions are enabled by default
#endif
enum
{
PAGE_ERASED = 0x1, // One or more erased pages found.
PAGE_DATA = 0x2, // One or more data pages found.
PAGE_SWAP_CLEAN = 0x4, // A clean (empty) swap page was found.
PAGE_SWAP_DIRTY = 0x8, // A dirty (non-empty) swap page was found.
};
typedef enum
{
// No erased pages or FDS pages found.
// This is a fatal error.
NO_PAGES,
// The filesystem can not be garbage collected.
// This is a fatal error.
NO_SWAP = (PAGE_DATA),
// Perform a fresh installation.
FRESH_INSTALL = (PAGE_ERASED),
// Tag an erased page as swap.
TAG_SWAP = (PAGE_ERASED | PAGE_DATA),
// Tag all erased pages as data.
TAG_DATA = (PAGE_ERASED | PAGE_SWAP_CLEAN),
// Tag all remaining erased pages as data.
TAG_DATA_INST = (PAGE_ERASED | PAGE_DATA | PAGE_SWAP_CLEAN),
// The swap is dirty, likely because the device powered off during GC.
// Because there is also an erased page, assume that that page has been garbage collected.
// Hence, tag the swap as data (promote), an erased page as swap and remaining pages as data.
PROMOTE_SWAP = (PAGE_ERASED | PAGE_SWAP_DIRTY),
// Tag the swap as data (promote), an erased page as swap and remaining pages as data.
PROMOTE_SWAP_INST = (PAGE_ERASED | PAGE_DATA | PAGE_SWAP_DIRTY),
// The swap is dirty (written) and there are no erased pages. It is likely that the device
// powered off during GC. It is safe to discard (erase) the swap, since data that was
// swapped out still lies in one of the valid pages.
DISCARD_SWAP = (PAGE_DATA | PAGE_SWAP_DIRTY),
// Do nothing.
ALREADY_INSTALLED = (PAGE_DATA | PAGE_SWAP_CLEAN),
} fds_init_opts_t;
typedef enum
{
GC_BEGIN, // Begin GC.
GC_NEXT_PAGE, // GC a page.
GC_FIND_NEXT_RECORD, // Find a valid record to copy.
GC_COPY_RECORD, // Copy a valid record to swap.
GC_ERASE_PAGE, // Erase the page being garbage collected.
GC_DISCARD_SWAP, // Erase (discard) the swap page.
GC_PROMOTE_SWAP, // Tag the swap as valid.
GC_TAG_NEW_SWAP // Tag a freshly erased (GCed) page as swap.
} fds_gc_state_t;
// Holds garbage collection status and related data.
typedef struct
{
fds_gc_state_t state; // The current GC step.
uint16_t cur_page; // The current page being garbage collected.
uint32_t const * p_record_src; // The current record being copied to swap.
uint16_t run_count; // Total number of times GC was run.
bool do_gc_page[FDS_DATA_PAGES]; // Controls which pages to garbage collect.
bool resume; // Whether or not GC should be resumed.
} fds_gc_data_t;
// Macros to enable and disable application interrupts.
#if defined (FDS_THREADS)
#define CRITICAL_SECTION_ENTER() CRITICAL_REGION_ENTER()
#define CRITICAL_SECTION_EXIT() CRITICAL_REGION_EXIT()
#else
#define CRITICAL_SECTION_ENTER()
#define CRITICAL_SECTION_EXIT()
#endif
#ifdef __cplusplus
}
#endif
#endif // FDS_INTERNAL_DEFS_H__

View File

@ -0,0 +1,313 @@
/**
* Copyright (c) 2012 - 2017, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ble_flash.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include "nrf_soc.h"
#include "nordic_common.h"
#include "nrf_error.h"
#include "nrf.h"
#include "app_util.h"
static volatile bool m_radio_active = false; /**< TRUE if radio is active (or about to become active), FALSE otherwise. */
uint16_t ble_flash_crc16_compute(uint8_t * p_data, uint16_t size, uint16_t * p_crc)
{
uint16_t i;
uint16_t crc = (p_crc == NULL) ? 0xffff : *p_crc;
for (i = 0; i < size; i++)
{
crc = (unsigned char)(crc >> 8) | (crc << 8);
crc ^= p_data[i];
crc ^= (unsigned char)(crc & 0xff) >> 4;
crc ^= (crc << 8) << 4;
crc ^= ((crc & 0xff) << 4) << 1;
}
return crc;
}
/**@brief Function for erasing a page in flash.
*
* @param[in] p_page Pointer to first word in page to be erased.
*/
static void flash_page_erase(uint32_t * p_page)
{
// Turn on flash erase enable and wait until the NVMC is ready.
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Een << NVMC_CONFIG_WEN_Pos);
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
// Do nothing.
}
// Erase page.
NRF_NVMC->ERASEPAGE = (uint32_t)p_page;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
// Do nothing.
}
// Turn off flash erase enable and wait until the NVMC is ready.
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
// Do nothing
}
}
/**@brief Function for writing one word to flash. Unprotected write, which can interfere with radio communication.
*
* @details This function DOES NOT use the m_radio_active variable, but will force the write even
* when the radio is active. To be used only from @ref ble_flash_page_write.
*
* @note Flash location to be written must have been erased previously.
*
* @param[in] p_address Pointer to flash location to be written.
* @param[in] value Value to write to flash.
*/
static void flash_word_unprotected_write(uint32_t * p_address, uint32_t value)
{
// Turn on flash write enable and wait until the NVMC is ready.
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos);
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
// Do nothing.
}
*p_address = value;
// Wait flash write to finish
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
// Do nothing.
}
// Turn off flash write enable and wait until the NVMC is ready.
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
// Do nothing.
}
}
/**@brief Function for writing one word to flash.
*
* @note Flash location to be written must have been erased previously.
*
* @param[in] p_address Pointer to flash location to be written.
* @param[in] value Value to write to flash.
*/
static void flash_word_write(uint32_t * p_address, uint32_t value)
{
// If radio is active, wait for it to become inactive.
while (m_radio_active)
{
// Do nothing (just wait for radio to become inactive).
(void) sd_app_evt_wait();
}
// Turn on flash write enable and wait until the NVMC is ready.
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos);
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
// Do nothing.
}
*p_address = value;
// Wait flash write to finish
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
// Do nothing.
}
// Turn off flash write enable and wait until the NVMC is ready.
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
// Do nothing
}
}
uint32_t ble_flash_word_write(uint32_t * p_address, uint32_t value)
{
flash_word_write(p_address, value);
return NRF_SUCCESS;
}
uint32_t ble_flash_block_write(uint32_t * p_address, uint32_t * p_in_array, uint16_t word_count)
{
uint16_t i;
for (i = 0; i < word_count; i++)
{
flash_word_write(p_address, p_in_array[i]);
p_address++;
}
return NRF_SUCCESS;
}
uint32_t ble_flash_page_erase(uint8_t page_num)
{
uint32_t * p_page = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num);
flash_page_erase(p_page);
return NRF_SUCCESS;
}
uint32_t ble_flash_page_write(uint8_t page_num, uint32_t * p_in_array, uint8_t word_count)
{
int i;
uint32_t * p_page;
uint32_t * p_curr_addr;
uint16_t in_data_crc;
uint16_t flash_crc;
uint32_t flash_header;
p_page = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num);
p_curr_addr = p_page;
// Calculate CRC of the data to write.
in_data_crc = ble_flash_crc16_compute((uint8_t *)p_in_array,
word_count * sizeof(uint32_t),
NULL);
// Compare the calculated to the one in flash.
flash_header = *p_curr_addr;
flash_crc = (uint16_t)flash_header;
if (flash_crc == in_data_crc)
{
// Data is the same as the data already stored in flash, return without modifying flash.
return NRF_SUCCESS;
}
// Erase flash page
flash_page_erase(p_page);
// Reserve space for magic number (for detecting if flash content is valid).
p_curr_addr++;
// Reserve space for saving word_count.
p_curr_addr++;
// Write data
for (i = 0; i < word_count; i++)
{
flash_word_unprotected_write(p_curr_addr, p_in_array[i]);
p_curr_addr++;
}
// Write number of elements.
flash_word_write(p_page + 1, (uint32_t)(word_count));
// Write magic number and CRC to indicate that flash content is valid.
flash_header = BLE_FLASH_MAGIC_NUMBER | (uint32_t)in_data_crc;
flash_word_write(p_page, flash_header);
return NRF_SUCCESS;
}
uint32_t ble_flash_page_read(uint8_t page_num, uint32_t * p_out_array, uint8_t * p_word_count)
{
int byte_count;
uint32_t * p_page;
uint32_t * p_curr_addr;
uint32_t flash_header;
uint32_t calc_header;
uint16_t calc_crc;
uint32_t tmp;
p_page = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num);
p_curr_addr = p_page;
// Check if block is valid
flash_header = *p_curr_addr;
tmp = flash_header & 0xFFFF0000;
if (tmp != BLE_FLASH_MAGIC_NUMBER)
{
*p_word_count = 0;
return NRF_ERROR_NOT_FOUND;
}
p_curr_addr++;
// Read number of elements
*p_word_count = (uint8_t)(*(p_curr_addr));
p_curr_addr++;
// Read data
byte_count = (*p_word_count) * sizeof(uint32_t);
memcpy(p_out_array, p_curr_addr, byte_count);
// Check CRC
calc_crc = ble_flash_crc16_compute((uint8_t *)p_out_array,
(*p_word_count) * sizeof(uint32_t),
NULL);
calc_header = BLE_FLASH_MAGIC_NUMBER | (uint32_t)calc_crc;
if (calc_header != flash_header)
{
return NRF_ERROR_NOT_FOUND;
}
return NRF_SUCCESS;
}
uint32_t ble_flash_page_addr(uint8_t page_num, uint32_t ** pp_page_addr)
{
*pp_page_addr = (uint32_t *)(BLE_FLASH_PAGE_SIZE * page_num);
return NRF_SUCCESS;
}
void ble_flash_on_radio_active_evt(bool radio_active)
{
m_radio_active = radio_active;
}

View File

@ -0,0 +1,178 @@
/**
* Copyright (c) 2012 - 2017, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** @file
*
* @defgroup ble_flash_module Flash Manager
* @{
* @ingroup ble_sdk_lib
* @brief Module for accessing flash memory.
*
* @details It contains functions for reading, writing and erasing one page in flash.
*
* The module uses the first 32 bits of the flash page to write a magic number in order to
* determine if the page has been written or not.
*
* @note Be careful not to use a page number in the SoftDevice area (which currently occupies the
* range 0 to 127), or in your application space! In both cases, this would end up
* with a hard fault.
*/
#ifndef BLE_FLASH_H__
#define BLE_FLASH_H__
#include <stdint.h>
#include <stdbool.h>
#include "nrf.h"
#ifdef __cplusplus
extern "C" {
#endif
#define BLE_FLASH_PAGE_SIZE ((uint16_t)NRF_FICR->CODEPAGESIZE) /**< Size of one flash page. */
#define BLE_FLASH_MAGIC_NUMBER 0x45DE0000 /**< Magic value to identify if flash contains valid data. */
#define BLE_FLASH_EMPTY_MASK 0xFFFFFFFF /**< Bit mask that defines an empty address in flash. */
/**@brief Macro for getting the end of the flash available for application.
*
* @details The result flash page number indicates the end boundary of the flash available
* to the application. If a bootloader is used, the end will be the start of the
* bootloader region. Otherwise, the end will be the size of the flash.
*/
#define BLE_FLASH_PAGE_END \
((NRF_UICR->NRFFW[0] != BLE_FLASH_EMPTY_MASK) \
? (NRF_UICR->NRFFW[0] / BLE_FLASH_PAGE_SIZE) \
: NRF_FICR->CODESIZE)
/**@brief Function for erasing the specified flash page, and then writes the given data to this page.
*
* @warning This operation blocks the CPU. DO NOT use while in a connection!
*
* @param[in] page_num Page number to update.
* @param[in] p_in_array Pointer to a RAM area containing the elements to write in flash.
* This area has to be 32 bits aligned.
* @param[in] word_count Number of 32 bits words to write in flash.
*
* @return NRF_SUCCESS on successful flash write, otherwise an error code.
*/
uint32_t ble_flash_page_write(uint8_t page_num, uint32_t * p_in_array, uint8_t word_count);
/**@brief Function for reading data from flash to RAM.
*
* @param[in] page_num Page number to read.
* @param[out] p_out_array Pointer to a RAM area where the found data will be written.
* This area has to be 32 bits aligned.
* @param[out] p_word_count Number of 32 bits words read.
*
* @return NRF_SUCCESS on successful upload, NRF_ERROR_NOT_FOUND if no valid data has been found
* in flash (first 32 bits not equal to the MAGIC_NUMBER + CRC).
*/
uint32_t ble_flash_page_read(uint8_t page_num, uint32_t * p_out_array, uint8_t * p_word_count);
/**@brief Function for erasing a flash page.
*
* @note This operation blocks the CPU, so it should not be done while the radio is running!
*
* @param[in] page_num Page number to erase.
*
* @return NRF_SUCCESS on success, an error_code otherwise.
*/
uint32_t ble_flash_page_erase(uint8_t page_num);
/**@brief Function for writing one word to flash.
*
* @note Flash location to be written must have been erased previously.
*
* @param[in] p_address Pointer to flash location to be written.
* @param[in] value Value to write to flash.
*
* @return NRF_SUCCESS.
*/
uint32_t ble_flash_word_write(uint32_t * p_address, uint32_t value);
/**@brief Function for writing a data block to flash.
*
* @note Flash locations to be written must have been erased previously.
*
* @param[in] p_address Pointer to start of flash location to be written.
* @param[in] p_in_array Pointer to start of flash block to be written.
* @param[in] word_count Number of words to be written.
*
* @return NRF_SUCCESS.
*/
uint32_t ble_flash_block_write(uint32_t * p_address, uint32_t * p_in_array, uint16_t word_count);
/**@brief Function for computing pointer to start of specified flash page.
*
* @param[in] page_num Page number.
* @param[out] pp_page_addr Pointer to start of flash page.
*
* @return NRF_SUCCESS.
*/
uint32_t ble_flash_page_addr(uint8_t page_num, uint32_t ** pp_page_addr);
/**@brief Function for calculating a 16 bit CRC using the CRC-16-CCITT scheme.
*
* @param[in] p_data Pointer to data on which the CRC is to be calculated.
* @param[in] size Number of bytes on which the CRC is to be calculated.
* @param[in] p_crc Initial CRC value (if NULL, a preset value is used as the initial value).
*
* @return Calculated CRC.
*/
uint16_t ble_flash_crc16_compute(uint8_t * p_data, uint16_t size, uint16_t * p_crc);
/**@brief Function for handling flashing module Radio Notification event.
*
* @note For flash writing to work safely while in a connection or while advertising, this function
* MUST be called from the Radio Notification module's event handler (see
* @ref ble_radio_notification for details).
*
* @param[in] radio_active TRUE if radio is active (or about to become active), FALSE otherwise.
*/
void ble_flash_on_radio_active_evt(bool radio_active);
#ifdef __cplusplus
}
#endif
#endif // BLE_FLASH_H__
/** @} */

View File

@ -135,8 +135,8 @@ typedef struct
* @brief Macro for creating a TWI master driver instance.
*/
// Mbed - need these
#define NRF_TWIM0_ENABLED 1
#define NRF_TWIM1_ENABLED 1
//#define NRF_TWIM0_ENABLED 1
//#define NRF_TWIM1_ENABLED 1
#define NRF_DRV_TWI_INSTANCE(id) NRF_DRV_TWI_INSTANCE_(id)
#define NRF_DRV_TWI_INSTANCE_(id) NRF_DRV_TWI_INSTANCE_ ## id

View File

@ -55,7 +55,7 @@ extern "C" {
*/
// RF - remove the legacy layer... this is preventing driver instances from being generated
//#include <legacy/apply_old_config.h>
#include <legacy/apply_old_config.h>
#include <soc/nrfx_irqs.h>

View File

@ -1,6 +1,6 @@
/**
* Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
*
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -566,7 +566,7 @@ static void uarte_irq_handler(NRF_UARTE_Type * p_uarte,
}
}
#if NRFX_CHECK(NRFX_UARTE0_ENABLED)
#if ( NRFX_CHECK(NRFX_UARTE0_ENABLED) && !(NRFX_CHECK(NRFX_UART0_ENABLED)))
void nrfx_uarte_0_irq_handler(void)
{
uarte_irq_handler(NRF_UARTE0, &m_cb[NRFX_UARTE0_INST_IDX]);