mirror of https://github.com/ARMmbed/mbed-os.git
Bringing in Softdevice but excluding BLE feature and improvements in feature defines
parent
511f8ebbd7
commit
cd5b451320
|
@ -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);
|
||||
}
|
|
@ -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__
|
||||
|
||||
/** @} */
|
|
@ -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;
|
||||
}
|
|
@ -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__
|
||||
|
||||
/** @} */
|
|
@ -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__
|
||||
|
||||
/** @} */
|
|
@ -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__
|
||||
/** @} */
|
|
@ -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)
|
|
@ -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__
|
||||
|
||||
/** @} */
|
|
@ -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)
|
|
@ -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__
|
||||
|
||||
/** @} */
|
|
@ -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)
|
|
@ -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__
|
||||
|
||||
/** @} */
|
|
@ -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)
|
|
@ -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__
|
||||
|
||||
/** @} */
|
|
@ -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
|
@ -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__
|
|
@ -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__
|
|
@ -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;
|
||||
}
|
|
@ -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__
|
||||
|
||||
/** @} */
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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]);
|
||||
|
|
Loading…
Reference in New Issue