Baseline legacy build using 14.2 drivers.

pull/10652/head
RFulchiero 2018-06-26 16:36:13 -05:00 committed by desmond.chen
parent 1dbb478bbb
commit 6bd89e7939
242 changed files with 136488 additions and 0 deletions

View File

@ -0,0 +1,35 @@
Copyright (c) 2007 - 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.

View File

@ -0,0 +1,622 @@
/*
* 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.
*/
/**
@addtogroup BLE_COMMON BLE SoftDevice Common
@{
@defgroup ble_api Events, type definitions and API calls
@{
@brief Module independent events, type definitions and API calls for the BLE SoftDevice.
*/
#ifndef BLE_H__
#define BLE_H__
#include <stdint.h>
#include "nrf_svc.h"
#include "nrf_error.h"
#include "ble_err.h"
#include "ble_gap.h"
#include "ble_l2cap.h"
#include "ble_gatt.h"
#include "ble_gattc.h"
#include "ble_gatts.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup BLE_COMMON_ENUMERATIONS Enumerations
* @{ */
/**
* @brief Common API SVC numbers.
*/
enum BLE_COMMON_SVCS
{
SD_BLE_ENABLE = BLE_SVC_BASE, /**< Enable and initialize the BLE stack */
SD_BLE_EVT_GET, /**< Get an event from the pending events queue. */
SD_BLE_UUID_VS_ADD, /**< Add a Vendor Specific UUID. */
SD_BLE_UUID_DECODE, /**< Decode UUID bytes. */
SD_BLE_UUID_ENCODE, /**< Encode UUID bytes. */
SD_BLE_VERSION_GET, /**< Get the local version information (company ID, Link Layer Version, Link Layer Subversion). */
SD_BLE_USER_MEM_REPLY, /**< User Memory Reply. */
SD_BLE_OPT_SET, /**< Set a BLE option. */
SD_BLE_OPT_GET, /**< Get a BLE option. */
SD_BLE_CFG_SET, /**< Add a configuration to the BLE stack. */
};
/**
* @brief BLE Module Independent Event IDs.
*/
enum BLE_COMMON_EVTS
{
BLE_EVT_USER_MEM_REQUEST = BLE_EVT_BASE + 0, /**< User Memory request. @ref ble_evt_user_mem_request_t */
BLE_EVT_USER_MEM_RELEASE = BLE_EVT_BASE + 1, /**< User Memory release. @ref ble_evt_user_mem_release_t */
};
/**@brief BLE Connection Configuration IDs.
*
* IDs that uniquely identify a connection configuration.
*/
enum BLE_CONN_CFGS
{
BLE_CONN_CFG_GAP = BLE_CONN_CFG_BASE + 0, /**< BLE GAP specific connection configuration. */
BLE_CONN_CFG_GATTC = BLE_CONN_CFG_BASE + 1, /**< BLE GATTC specific connection configuration. */
BLE_CONN_CFG_GATTS = BLE_CONN_CFG_BASE + 2, /**< BLE GATTS specific connection configuration. */
BLE_CONN_CFG_GATT = BLE_CONN_CFG_BASE + 3, /**< BLE GATT specific connection configuration. */
BLE_CONN_CFG_L2CAP = BLE_CONN_CFG_BASE + 4, /**< BLE L2CAP specific connection configuration. */
};
/**@brief BLE Common Configuration IDs.
*
* IDs that uniquely identify a common configuration.
*/
enum BLE_COMMON_CFGS
{
BLE_COMMON_CFG_VS_UUID = BLE_CFG_BASE, /**< Vendor specific UUID configuration */
};
/**@brief Common Option IDs.
* IDs that uniquely identify a common option.
*/
enum BLE_COMMON_OPTS
{
BLE_COMMON_OPT_PA_LNA = BLE_OPT_BASE + 0, /**< PA and LNA options */
BLE_COMMON_OPT_CONN_EVT_EXT = BLE_OPT_BASE + 1, /**< Extended connection events option */
};
/** @} */
/** @addtogroup BLE_COMMON_DEFINES Defines
* @{ */
/** @brief Required pointer alignment for BLE Events.
*/
#define BLE_EVT_PTR_ALIGNMENT 4
/** @brief Leaves the maximum of the two arguments.
*/
#define BLE_MAX(a, b) ((a) < (b) ? (b) : (a))
/** @brief Maximum possible length for BLE Events.
* @note The highest value used for @ref ble_gatt_conn_cfg_t::att_mtu in any connection configuration shall be used as a parameter.
* If that value has not been configured for any connections then @ref BLE_GATT_ATT_MTU_DEFAULT must be used instead.
*/
#define BLE_EVT_LEN_MAX(ATT_MTU) ( \
offsetof(ble_evt_t, evt.gattc_evt.params.prim_srvc_disc_rsp.services) + ((ATT_MTU) - 1) / 4 * sizeof(ble_gattc_service_t) \
)
/** @defgroup BLE_USER_MEM_TYPES User Memory Types
* @{ */
#define BLE_USER_MEM_TYPE_INVALID 0x00 /**< Invalid User Memory Types. */
#define BLE_USER_MEM_TYPE_GATTS_QUEUED_WRITES 0x01 /**< User Memory for GATTS queued writes. */
/** @} */
/** @defgroup BLE_UUID_VS_COUNTS Vendor Specific UUID counts
* @{
*/
#define BLE_UUID_VS_COUNT_DEFAULT 10 /**< Default VS UUID count. */
#define BLE_UUID_VS_COUNT_MAX 254 /**< Maximum VS UUID count. */
/** @} */
/** @defgroup BLE_COMMON_CFG_DEFAULTS Configuration defaults.
* @{
*/
#define BLE_CONN_CFG_TAG_DEFAULT 0 /**< Default configuration tag, SoftDevice default connection configuration. */
/** @} */
/** @} */
/** @addtogroup BLE_COMMON_STRUCTURES Structures
* @{ */
/**@brief User Memory Block. */
typedef struct
{
uint8_t *p_mem; /**< Pointer to the start of the user memory block. */
uint16_t len; /**< Length in bytes of the user memory block. */
} ble_user_mem_block_t;
/**@brief Event structure for @ref BLE_EVT_USER_MEM_REQUEST. */
typedef struct
{
uint8_t type; /**< User memory type, see @ref BLE_USER_MEM_TYPES. */
} ble_evt_user_mem_request_t;
/**@brief Event structure for @ref BLE_EVT_USER_MEM_RELEASE. */
typedef struct
{
uint8_t type; /**< User memory type, see @ref BLE_USER_MEM_TYPES. */
ble_user_mem_block_t mem_block; /**< User memory block */
} ble_evt_user_mem_release_t;
/**@brief Event structure for events not associated with a specific function module. */
typedef struct
{
uint16_t conn_handle; /**< Connection Handle on which this event occurred. */
union
{
ble_evt_user_mem_request_t user_mem_request; /**< User Memory Request Event Parameters. */
ble_evt_user_mem_release_t user_mem_release; /**< User Memory Release Event Parameters. */
} params; /**< Event parameter union. */
} ble_common_evt_t;
/**@brief BLE Event header. */
typedef struct
{
uint16_t evt_id; /**< Value from a BLE_<module>_EVT series. */
uint16_t evt_len; /**< Length in octets including this header. */
} ble_evt_hdr_t;
/**@brief Common BLE Event type, wrapping the module specific event reports. */
typedef struct
{
ble_evt_hdr_t header; /**< Event header. */
union
{
ble_common_evt_t common_evt; /**< Common Event, evt_id in BLE_EVT_* series. */
ble_gap_evt_t gap_evt; /**< GAP originated event, evt_id in BLE_GAP_EVT_* series. */
ble_gattc_evt_t gattc_evt; /**< GATT client originated event, evt_id in BLE_GATTC_EVT* series. */
ble_gatts_evt_t gatts_evt; /**< GATT server originated event, evt_id in BLE_GATTS_EVT* series. */
ble_l2cap_evt_t l2cap_evt; /**< L2CAP originated event, evt_id in BLE_L2CAP_EVT* series. */
} evt; /**< Event union. */
} ble_evt_t;
/**
* @brief Version Information.
*/
typedef struct
{
uint8_t version_number; /**< Link Layer Version number. See https://www.bluetooth.org/en-us/specification/assigned-numbers/link-layer for assigned values. */
uint16_t company_id; /**< Company ID, Nordic Semiconductor's company ID is 89 (0x0059) (https://www.bluetooth.org/apps/content/Default.aspx?doc_id=49708). */
uint16_t subversion_number; /**< Link Layer Sub Version number, corresponds to the SoftDevice Config ID or Firmware ID (FWID). */
} ble_version_t;
/**
* @brief Configuration parameters for the PA and LNA.
*/
typedef struct
{
uint8_t enable :1; /**< Enable toggling for this amplifier */
uint8_t active_high :1; /**< Set the pin to be active high */
uint8_t gpio_pin :6; /**< The GPIO pin to toggle for this amplifier */
} ble_pa_lna_cfg_t;
/**
* @brief PA & LNA GPIO toggle configuration
*
* This option configures the SoftDevice to toggle pins when the radio is active for use with a power amplifier and/or
* a low noise amplifier.
*
* Toggling the pins is achieved by using two PPI channels and a GPIOTE channel. The hardware channel IDs are provided
* by the application and should be regarded as reserved as long as any PA/LNA toggling is enabled.
*
* @note @ref sd_ble_opt_get is not supported for this option.
* @note Setting this option while the radio is in use (i.e. any of the roles are active) may have undefined consequences
* and must be avoided by the application.
*/
typedef struct
{
ble_pa_lna_cfg_t pa_cfg; /**< Power Amplifier configuration */
ble_pa_lna_cfg_t lna_cfg; /**< Low Noise Amplifier configuration */
uint8_t ppi_ch_id_set; /**< PPI channel used for radio pin setting */
uint8_t ppi_ch_id_clr; /**< PPI channel used for radio pin clearing */
uint8_t gpiote_ch_id; /**< GPIOTE channel used for radio pin toggling */
} ble_common_opt_pa_lna_t;
/**
* @brief Configuration of extended BLE connection events.
*
* When enabled the SoftDevice will dynamically extend the connection event when possible.
*
* The connection event length is controlled by the connection configuration as set by @ref ble_gap_conn_cfg_t::event_length.
* The connection event can be extended if there is time to send another packet pair before the start of the next connection interval,
* and if there are no conflicts with other BLE roles requesting radio time.
*
* @note @ref sd_ble_opt_get is not supported for this option.
*/
typedef struct
{
uint8_t enable : 1; /**< Enable extended BLE connection events, disabled by default. */
} ble_common_opt_conn_evt_ext_t;
/**@brief Option structure for common options. */
typedef union
{
ble_common_opt_pa_lna_t pa_lna; /**< Parameters for controlling PA and LNA pin toggling. */
ble_common_opt_conn_evt_ext_t conn_evt_ext; /**< Parameters for enabling extended connection events. */
} ble_common_opt_t;
/**@brief Common BLE Option type, wrapping the module specific options. */
typedef union
{
ble_common_opt_t common_opt; /**< COMMON options, opt_id in @ref BLE_COMMON_OPTS series. */
ble_gap_opt_t gap_opt; /**< GAP option, opt_id in @ref BLE_GAP_OPTS series. */
} ble_opt_t;
/**@brief BLE connection configuration type, wrapping the module specific configurations, set with
* @ref sd_ble_cfg_set.
*
* @note Connection configurations don't have to be set.
* In the case that no configurations has been set, or fewer connection configurations has been set than enabled connections,
* the default connection configuration will be automatically added for the remaining connections.
* When creating connections with the default configuration, @ref BLE_CONN_CFG_TAG_DEFAULT should be used in
* place of @ref ble_conn_cfg_t::conn_cfg_tag.
*
* @sa sd_ble_gap_adv_start()
* @sa sd_ble_gap_connect()
*
* @mscs
* @mmsc{@ref BLE_CONN_CFG}
* @endmscs
*/
typedef struct
{
uint8_t conn_cfg_tag; /**< The application chosen tag it can use with the
@ref sd_ble_gap_adv_start() and @ref sd_ble_gap_connect() calls
to select this configuration when creating a connection.
Must be different for all connection configurations added and not @ref BLE_CONN_CFG_TAG_DEFAULT. */
union {
ble_gap_conn_cfg_t gap_conn_cfg; /**< GAP connection configuration, cfg_id is @ref BLE_CONN_CFG_GAP. */
ble_gattc_conn_cfg_t gattc_conn_cfg; /**< GATTC connection configuration, cfg_id is @ref BLE_CONN_CFG_GATTC. */
ble_gatts_conn_cfg_t gatts_conn_cfg; /**< GATTS connection configuration, cfg_id is @ref BLE_CONN_CFG_GATTS. */
ble_gatt_conn_cfg_t gatt_conn_cfg; /**< GATT connection configuration, cfg_id is @ref BLE_CONN_CFG_GATT. */
ble_l2cap_conn_cfg_t l2cap_conn_cfg; /**< L2CAP connection configuration, cfg_id is @ref BLE_CONN_CFG_L2CAP. */
} params; /**< Connection configuration union. */
} ble_conn_cfg_t;
/**
* @brief Configuration of Vendor Specific UUIDs, set with @ref sd_ble_cfg_set.
*
* @retval ::NRF_ERROR_INVALID_PARAM Too many UUIDs configured.
*/
typedef struct
{
uint8_t vs_uuid_count; /**< Number of 128-bit Vendor Specific UUID bases to allocate memory for.
Default value is @ref BLE_UUID_VS_COUNT_DEFAULT. Maximum value is
@ref BLE_UUID_VS_COUNT_MAX. */
} ble_common_cfg_vs_uuid_t;
/**@brief Common BLE Configuration type, wrapping the common configurations. */
typedef union
{
ble_common_cfg_vs_uuid_t vs_uuid_cfg; /**< Vendor specific UUID configuration, cfg_id is @ref BLE_COMMON_CFG_VS_UUID. */
} ble_common_cfg_t;
/**@brief BLE Configuration type, wrapping the module specific configurations. */
typedef union
{
ble_conn_cfg_t conn_cfg; /**< Connection specific configurations, cfg_id in @ref BLE_CONN_CFGS series. */
ble_common_cfg_t common_cfg; /**< Global common configurations, cfg_id in @ref BLE_COMMON_CFGS series. */
ble_gap_cfg_t gap_cfg; /**< Global GAP configurations, cfg_id in @ref BLE_GAP_CFGS series. */
ble_gatts_cfg_t gatts_cfg; /**< Global GATTS configuration, cfg_id in @ref BLE_GATTS_CFGS series. */
} ble_cfg_t;
/** @} */
/** @addtogroup BLE_COMMON_FUNCTIONS Functions
* @{ */
/**@brief Enable the BLE stack
*
* @param[in, out] p_app_ram_base Pointer to a variable containing the start address of the
* application RAM region (APP_RAM_BASE). On return, this will
* contain the minimum start address of the application RAM region
* required by the SoftDevice for this configuration.
*
* @note The memory requirement for a specific configuration will not increase between SoftDevices
* with the same major version number.
*
* @note The value of *p_app_ram_base when the app has done no custom configuration of the
* SoftDevice, i.e. the app has not called @ref sd_ble_cfg_set before @ref sd_ble_enable, can
* be found in the release notes.
*
* @note At runtime the IC's RAM is split into 2 regions: The SoftDevice RAM region is located
* between 0x20000000 and APP_RAM_BASE-1 and the application's RAM region is located between
* APP_RAM_BASE and the start of the call stack.
*
* @details This call initializes the BLE stack, no BLE related function other than @ref
* sd_ble_cfg_set can be called before this one.
*
* @mscs
* @mmsc{@ref BLE_COMMON_ENABLE}
* @endmscs
*
* @retval ::NRF_SUCCESS The BLE stack has been initialized successfully.
* @retval ::NRF_ERROR_INVALID_STATE The BLE stack had already been initialized and cannot be reinitialized.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid or not sufficiently aligned pointer supplied.
* @retval ::NRF_ERROR_NO_MEM The amount of memory assigned to the SoftDevice by *p_app_ram_base is not
* large enough to fit this configuration's memory requirement. Check *p_app_ram_base
* and set the start address of the application RAM region accordingly.
*/
SVCALL(SD_BLE_ENABLE, uint32_t, sd_ble_enable(uint32_t * p_app_ram_base));
/**@brief Add configurations for the BLE stack
*
* @param[in] cfg_id Config ID, see @ref BLE_CONN_CFGS, @ref BLE_COMMON_CFGS, @ref
* BLE_GAP_CFGS or @ref BLE_GATTS_CFGS.
* @param[in] p_cfg Pointer to a ble_cfg_t structure containing the configuration value.
* @param[in] app_ram_base The start address of the application RAM region (APP_RAM_BASE).
* See @ref sd_ble_enable for details about APP_RAM_BASE.
*
* @note The memory requirement for a specific configuration will not increase between SoftDevices
* with the same major version number.
*
* @note If a configuration is set more than once, the last one set is the one that takes effect on
* @ref sd_ble_enable.
*
* @note Any part of the BLE stack that is NOT configured with @ref sd_ble_cfg_set will have default
* configuration.
*
* @note @ref sd_ble_cfg_set may be called at any time when the SoftDevice is enabled (see @ref
* sd_softdevice_enable) while the BLE part of the SoftDevice is not enabled (see @ref
* sd_ble_enable).
*
* @note Error codes for the configurations are described in the configuration structs.
*
* @mscs
* @mmsc{@ref BLE_COMMON_ENABLE}
* @endmscs
*
* @retval ::NRF_SUCCESS The configuration has been added successfully.
* @retval ::NRF_ERROR_INVALID_STATE The BLE stack had already been initialized.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid or not sufficiently aligned pointer supplied.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid cfg_id supplied.
* @retval ::NRF_ERROR_NO_MEM The amount of memory assigned to the SoftDevice by app_ram_base is not
* large enough to fit this configuration's memory requirement.
*/
SVCALL(SD_BLE_CFG_SET, uint32_t, sd_ble_cfg_set(uint32_t cfg_id, ble_cfg_t const * p_cfg, uint32_t app_ram_base));
/**@brief Get an event from the pending events queue.
*
* @param[out] p_dest Pointer to buffer to be filled in with an event, or NULL to retrieve the event length.
* This buffer <b>must be aligned to the extend defined by @ref BLE_EVT_PTR_ALIGNMENT</b>.
* The buffer should be interpreted as a @ref ble_evt_t struct.
* @param[in, out] p_len Pointer the length of the buffer, on return it is filled with the event length.
*
* @details This call allows the application to pull a BLE event from the BLE stack. The application is signaled that
* an event is available from the BLE stack by the triggering of the SD_EVT_IRQn interrupt.
* The application is free to choose whether to call this function from thread mode (main context) or directly from the
* Interrupt Service Routine that maps to SD_EVT_IRQn. In any case however, and because the BLE stack runs at a higher
* priority than the application, this function should be called in a loop (until @ref NRF_ERROR_NOT_FOUND is returned)
* every time SD_EVT_IRQn is raised to ensure that all available events are pulled from the BLE stack. Failure to do so
* could potentially leave events in the internal queue without the application being aware of this fact.
*
* Sizing the p_dest buffer is equally important, since the application needs to provide all the memory necessary for the event to
* be copied into application memory. If the buffer provided is not large enough to fit the entire contents of the event,
* @ref NRF_ERROR_DATA_SIZE will be returned and the application can then call again with a larger buffer size.
* The maximum possible event length is defined by @ref BLE_EVT_LEN_MAX. The application may also "peek" the event length
* by providing p_dest as a NULL pointer and inspecting the value of *p_len upon return:
*
* \code
* uint16_t len;
* errcode = sd_ble_evt_get(NULL, &len);
* \endcode
*
* @mscs
* @mmsc{@ref BLE_COMMON_IRQ_EVT_MSC}
* @mmsc{@ref BLE_COMMON_THREAD_EVT_MSC}
* @endmscs
*
* @retval ::NRF_SUCCESS Event pulled and stored into the supplied buffer.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid or not sufficiently aligned pointer supplied.
* @retval ::NRF_ERROR_NOT_FOUND No events ready to be pulled.
* @retval ::NRF_ERROR_DATA_SIZE Event ready but could not fit into the supplied buffer.
*/
SVCALL(SD_BLE_EVT_GET, uint32_t, sd_ble_evt_get(uint8_t *p_dest, uint16_t *p_len));
/**@brief Add a Vendor Specific base UUID.
*
* @details This call enables the application to add a vendor specific base UUID to the BLE stack's table, for later
* use with all other modules and APIs. This then allows the application to use the shorter, 24-bit @ref ble_uuid_t
* format when dealing with both 16-bit and 128-bit UUIDs without having to check for lengths and having split code
* paths. This is accomplished by extending the grouping mechanism that the Bluetooth SIG standard base UUID uses
* for all other 128-bit UUIDs. The type field in the @ref ble_uuid_t structure is an index (relative to
* @ref BLE_UUID_TYPE_VENDOR_BEGIN) to the table populated by multiple calls to this function, and the UUID field
* in the same structure contains the 2 bytes at indexes 12 and 13. The number of possible 128-bit UUIDs available to
* the application is therefore the number of Vendor Specific UUIDs added with the help of this function times 65536,
* although restricted to modifying bytes 12 and 13 for each of the entries in the supplied array.
*
* @note Bytes 12 and 13 of the provided UUID will not be used internally, since those are always replaced by
* the 16-bit uuid field in @ref ble_uuid_t.
*
* @note If a UUID is already present in the BLE stack's internal table, the corresponding index will be returned in
* p_uuid_type along with an @ref NRF_SUCCESS error code.
*
* @param[in] p_vs_uuid Pointer to a 16-octet (128-bit) little endian Vendor Specific UUID disregarding
* bytes 12 and 13.
* @param[out] p_uuid_type Pointer to a uint8_t where the type field in @ref ble_uuid_t corresponding to this UUID will be stored.
*
* @retval ::NRF_SUCCESS Successfully added the Vendor Specific UUID.
* @retval ::NRF_ERROR_INVALID_ADDR If p_vs_uuid or p_uuid_type is NULL or invalid.
* @retval ::NRF_ERROR_NO_MEM If there are no more free slots for VS UUIDs.
*/
SVCALL(SD_BLE_UUID_VS_ADD, uint32_t, sd_ble_uuid_vs_add(ble_uuid128_t const *p_vs_uuid, uint8_t *p_uuid_type));
/** @brief Decode little endian raw UUID bytes (16-bit or 128-bit) into a 24 bit @ref ble_uuid_t structure.
*
* @details The raw UUID bytes excluding bytes 12 and 13 (i.e. bytes 0-11 and 14-15) of p_uuid_le are compared
* to the corresponding ones in each entry of the table of vendor specific UUIDs populated with @ref sd_ble_uuid_vs_add
* to look for a match. If there is such a match, bytes 12 and 13 are returned as p_uuid->uuid and the index
* relative to @ref BLE_UUID_TYPE_VENDOR_BEGIN as p_uuid->type.
*
* @note If the UUID length supplied is 2, then the type set by this call will always be @ref BLE_UUID_TYPE_BLE.
*
* @param[in] uuid_le_len Length in bytes of the buffer pointed to by p_uuid_le (must be 2 or 16 bytes).
* @param[in] p_uuid_le Pointer pointing to little endian raw UUID bytes.
* @param[out] p_uuid Pointer to a @ref ble_uuid_t structure to be filled in.
*
* @retval ::NRF_SUCCESS Successfully decoded into the @ref ble_uuid_t structure.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_INVALID_LENGTH Invalid UUID length.
* @retval ::NRF_ERROR_NOT_FOUND For a 128-bit UUID, no match in the populated table of UUIDs.
*/
SVCALL(SD_BLE_UUID_DECODE, uint32_t, sd_ble_uuid_decode(uint8_t uuid_le_len, uint8_t const *p_uuid_le, ble_uuid_t *p_uuid));
/** @brief Encode a @ref ble_uuid_t structure into little endian raw UUID bytes (16-bit or 128-bit).
*
* @note The pointer to the destination buffer p_uuid_le may be NULL, in which case only the validity and size of p_uuid is computed.
*
* @param[in] p_uuid Pointer to a @ref ble_uuid_t structure that will be encoded into bytes.
* @param[out] p_uuid_le_len Pointer to a uint8_t that will be filled with the encoded length (2 or 16 bytes).
* @param[out] p_uuid_le Pointer to a buffer where the little endian raw UUID bytes (2 or 16) will be stored.
*
* @retval ::NRF_SUCCESS Successfully encoded into the buffer.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid UUID type.
*/
SVCALL(SD_BLE_UUID_ENCODE, uint32_t, sd_ble_uuid_encode(ble_uuid_t const *p_uuid, uint8_t *p_uuid_le_len, uint8_t *p_uuid_le));
/**@brief Get Version Information.
*
* @details This call allows the application to get the BLE stack version information.
*
* @param[out] p_version Pointer to a ble_version_t structure to be filled in.
*
* @retval ::NRF_SUCCESS Version information stored successfully.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_BUSY The BLE stack is busy (typically doing a locally-initiated disconnection procedure).
*/
SVCALL(SD_BLE_VERSION_GET, uint32_t, sd_ble_version_get(ble_version_t *p_version));
/**@brief Provide a user memory block.
*
* @note This call can only be used as a response to a @ref BLE_EVT_USER_MEM_REQUEST event issued to the application.
*
* @param[in] conn_handle Connection handle.
* @param[in] p_block Pointer to a user memory block structure or NULL if memory is managed by the application.
*
* @mscs
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_PEER_CANCEL_MSC}
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_NOBUF_AUTH_MSC}
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_NOBUF_NOAUTH_MSC}
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_BUF_AUTH_MSC}
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_BUF_NOAUTH_MSC}
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_QUEUE_FULL_MSC}
* @endmscs
*
* @retval ::NRF_SUCCESS Successfully queued a response to the peer.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_LENGTH Invalid user memory block length supplied.
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection state or no user memory request pending.
*/
SVCALL(SD_BLE_USER_MEM_REPLY, uint32_t, sd_ble_user_mem_reply(uint16_t conn_handle, ble_user_mem_block_t const *p_block));
/**@brief Set a BLE option.
*
* @details This call allows the application to set the value of an option.
*
* @mscs
* @mmsc{@ref BLE_GAP_PERIPH_BONDING_STATIC_PK_MSC}
* @endmscs
*
* @param[in] opt_id Option ID, see @ref BLE_COMMON_OPTS and @ref BLE_GAP_OPTS.
* @param[in] p_opt Pointer to a ble_opt_t structure containing the option value.
*
* @retval ::NRF_SUCCESS Option set successfully.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, check parameter limits and constraints.
* @retval ::NRF_ERROR_INVALID_STATE Unable to set the parameter at this time.
* @retval ::NRF_ERROR_BUSY The BLE stack is busy or the previous procedure has not completed.
*/
SVCALL(SD_BLE_OPT_SET, uint32_t, sd_ble_opt_set(uint32_t opt_id, ble_opt_t const *p_opt));
/**@brief Get a BLE option.
*
* @details This call allows the application to retrieve the value of an option.
*
* @param[in] opt_id Option ID, see @ref BLE_COMMON_OPTS and @ref BLE_GAP_OPTS.
* @param[out] p_opt Pointer to a ble_opt_t structure to be filled in.
*
* @retval ::NRF_SUCCESS Option retrieved successfully.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, check parameter limits and constraints.
* @retval ::NRF_ERROR_INVALID_STATE Unable to retrieve the parameter at this time.
* @retval ::NRF_ERROR_BUSY The BLE stack is busy or the previous procedure has not completed.
* @retval ::NRF_ERROR_NOT_SUPPORTED This option is not supported.
*
*/
SVCALL(SD_BLE_OPT_GET, uint32_t, sd_ble_opt_get(uint32_t opt_id, ble_opt_t *p_opt));
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* BLE_H__ */
/**
@}
@}
*/

View File

@ -0,0 +1,93 @@
/*
* 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.
*/
/**
@addtogroup BLE_COMMON
@{
@addtogroup nrf_error
@{
@ingroup BLE_COMMON
@}
@defgroup ble_err General error codes
@{
@brief General error code definitions for the BLE API.
@ingroup BLE_COMMON
*/
#ifndef NRF_BLE_ERR_H__
#define NRF_BLE_ERR_H__
#include "nrf_error.h"
#ifdef __cplusplus
extern "C" {
#endif
/* @defgroup BLE_ERRORS Error Codes
* @{ */
#define BLE_ERROR_NOT_ENABLED (NRF_ERROR_STK_BASE_NUM+0x001) /**< @ref sd_ble_enable has not been called. */
#define BLE_ERROR_INVALID_CONN_HANDLE (NRF_ERROR_STK_BASE_NUM+0x002) /**< Invalid connection handle. */
#define BLE_ERROR_INVALID_ATTR_HANDLE (NRF_ERROR_STK_BASE_NUM+0x003) /**< Invalid attribute handle. */
#define BLE_ERROR_INVALID_ADV_HANDLE (NRF_ERROR_STK_BASE_NUM+0x004) /**< Invalid advertising handle. */
#define BLE_ERROR_INVALID_ROLE (NRF_ERROR_STK_BASE_NUM+0x005) /**< Invalid role. */
#define BLE_ERROR_BLOCKED_BY_OTHER_LINKS (NRF_ERROR_STK_BASE_NUM+0x006) /**< The attempt to change link settings failed due to the scheduling of other links. */
/** @} */
/** @defgroup BLE_ERROR_SUBRANGES Module specific error code subranges
* @brief Assignment of subranges for module specific error codes.
* @note For specific error codes, see ble_<module>.h or ble_error_<module>.h.
* @{ */
#define NRF_L2CAP_ERR_BASE (NRF_ERROR_STK_BASE_NUM+0x100) /**< L2CAP specific errors. */
#define NRF_GAP_ERR_BASE (NRF_ERROR_STK_BASE_NUM+0x200) /**< GAP specific errors. */
#define NRF_GATTC_ERR_BASE (NRF_ERROR_STK_BASE_NUM+0x300) /**< GATT client specific errors. */
#define NRF_GATTS_ERR_BASE (NRF_ERROR_STK_BASE_NUM+0x400) /**< GATT server specific errors. */
/** @} */
#ifdef __cplusplus
}
#endif
#endif
/**
@}
@}
*/

View File

@ -0,0 +1,228 @@
/*
* Copyright (c) 2013 - 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.
*/
/**
@addtogroup BLE_GATT Generic Attribute Profile (GATT) Common
@{
@brief Common definitions and prototypes for the GATT interfaces.
*/
#ifndef BLE_GATT_H__
#define BLE_GATT_H__
#include <stdint.h>
#include "nrf_svc.h"
#include "nrf_error.h"
#include "ble_hci.h"
#include "ble_ranges.h"
#include "ble_types.h"
#include "ble_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup BLE_GATT_DEFINES Defines
* @{ */
/** @brief Default ATT MTU, in bytes. */
#define BLE_GATT_ATT_MTU_DEFAULT 23
/**@brief Invalid Attribute Handle. */
#define BLE_GATT_HANDLE_INVALID 0x0000
/**@brief First Attribute Handle. */
#define BLE_GATT_HANDLE_START 0x0001
/**@brief Last Attribute Handle. */
#define BLE_GATT_HANDLE_END 0xFFFF
/** @defgroup BLE_GATT_TIMEOUT_SOURCES GATT Timeout sources
* @{ */
#define BLE_GATT_TIMEOUT_SRC_PROTOCOL 0x00 /**< ATT Protocol timeout. */
/** @} */
/** @defgroup BLE_GATT_WRITE_OPS GATT Write operations
* @{ */
#define BLE_GATT_OP_INVALID 0x00 /**< Invalid Operation. */
#define BLE_GATT_OP_WRITE_REQ 0x01 /**< Write Request. */
#define BLE_GATT_OP_WRITE_CMD 0x02 /**< Write Command. */
#define BLE_GATT_OP_SIGN_WRITE_CMD 0x03 /**< Signed Write Command. */
#define BLE_GATT_OP_PREP_WRITE_REQ 0x04 /**< Prepare Write Request. */
#define BLE_GATT_OP_EXEC_WRITE_REQ 0x05 /**< Execute Write Request. */
/** @} */
/** @defgroup BLE_GATT_EXEC_WRITE_FLAGS GATT Execute Write flags
* @{ */
#define BLE_GATT_EXEC_WRITE_FLAG_PREPARED_CANCEL 0x00 /**< Cancel prepared write. */
#define BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE 0x01 /**< Execute prepared write. */
/** @} */
/** @defgroup BLE_GATT_HVX_TYPES GATT Handle Value operations
* @{ */
#define BLE_GATT_HVX_INVALID 0x00 /**< Invalid Operation. */
#define BLE_GATT_HVX_NOTIFICATION 0x01 /**< Handle Value Notification. */
#define BLE_GATT_HVX_INDICATION 0x02 /**< Handle Value Indication. */
/** @} */
/** @defgroup BLE_GATT_STATUS_CODES GATT Status Codes
* @{ */
#define BLE_GATT_STATUS_SUCCESS 0x0000 /**< Success. */
#define BLE_GATT_STATUS_UNKNOWN 0x0001 /**< Unknown or not applicable status. */
#define BLE_GATT_STATUS_ATTERR_INVALID 0x0100 /**< ATT Error: Invalid Error Code. */
#define BLE_GATT_STATUS_ATTERR_INVALID_HANDLE 0x0101 /**< ATT Error: Invalid Attribute Handle. */
#define BLE_GATT_STATUS_ATTERR_READ_NOT_PERMITTED 0x0102 /**< ATT Error: Read not permitted. */
#define BLE_GATT_STATUS_ATTERR_WRITE_NOT_PERMITTED 0x0103 /**< ATT Error: Write not permitted. */
#define BLE_GATT_STATUS_ATTERR_INVALID_PDU 0x0104 /**< ATT Error: Used in ATT as Invalid PDU. */
#define BLE_GATT_STATUS_ATTERR_INSUF_AUTHENTICATION 0x0105 /**< ATT Error: Authenticated link required. */
#define BLE_GATT_STATUS_ATTERR_REQUEST_NOT_SUPPORTED 0x0106 /**< ATT Error: Used in ATT as Request Not Supported. */
#define BLE_GATT_STATUS_ATTERR_INVALID_OFFSET 0x0107 /**< ATT Error: Offset specified was past the end of the attribute. */
#define BLE_GATT_STATUS_ATTERR_INSUF_AUTHORIZATION 0x0108 /**< ATT Error: Used in ATT as Insufficient Authorization. */
#define BLE_GATT_STATUS_ATTERR_PREPARE_QUEUE_FULL 0x0109 /**< ATT Error: Used in ATT as Prepare Queue Full. */
#define BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND 0x010A /**< ATT Error: Used in ATT as Attribute not found. */
#define BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_LONG 0x010B /**< ATT Error: Attribute cannot be read or written using read/write blob requests. */
#define BLE_GATT_STATUS_ATTERR_INSUF_ENC_KEY_SIZE 0x010C /**< ATT Error: Encryption key size used is insufficient. */
#define BLE_GATT_STATUS_ATTERR_INVALID_ATT_VAL_LENGTH 0x010D /**< ATT Error: Invalid value size. */
#define BLE_GATT_STATUS_ATTERR_UNLIKELY_ERROR 0x010E /**< ATT Error: Very unlikely error. */
#define BLE_GATT_STATUS_ATTERR_INSUF_ENCRYPTION 0x010F /**< ATT Error: Encrypted link required. */
#define BLE_GATT_STATUS_ATTERR_UNSUPPORTED_GROUP_TYPE 0x0110 /**< ATT Error: Attribute type is not a supported grouping attribute. */
#define BLE_GATT_STATUS_ATTERR_INSUF_RESOURCES 0x0111 /**< ATT Error: Encrypted link required. */
#define BLE_GATT_STATUS_ATTERR_RFU_RANGE1_BEGIN 0x0112 /**< ATT Error: Reserved for Future Use range #1 begin. */
#define BLE_GATT_STATUS_ATTERR_RFU_RANGE1_END 0x017F /**< ATT Error: Reserved for Future Use range #1 end. */
#define BLE_GATT_STATUS_ATTERR_APP_BEGIN 0x0180 /**< ATT Error: Application range begin. */
#define BLE_GATT_STATUS_ATTERR_APP_END 0x019F /**< ATT Error: Application range end. */
#define BLE_GATT_STATUS_ATTERR_RFU_RANGE2_BEGIN 0x01A0 /**< ATT Error: Reserved for Future Use range #2 begin. */
#define BLE_GATT_STATUS_ATTERR_RFU_RANGE2_END 0x01DF /**< ATT Error: Reserved for Future Use range #2 end. */
#define BLE_GATT_STATUS_ATTERR_RFU_RANGE3_BEGIN 0x01E0 /**< ATT Error: Reserved for Future Use range #3 begin. */
#define BLE_GATT_STATUS_ATTERR_RFU_RANGE3_END 0x01FC /**< ATT Error: Reserved for Future Use range #3 end. */
#define BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR 0x01FD /**< ATT Common Profile and Service Error: Client Characteristic Configuration Descriptor improperly configured. */
#define BLE_GATT_STATUS_ATTERR_CPS_PROC_ALR_IN_PROG 0x01FE /**< ATT Common Profile and Service Error: Procedure Already in Progress. */
#define BLE_GATT_STATUS_ATTERR_CPS_OUT_OF_RANGE 0x01FF /**< ATT Common Profile and Service Error: Out Of Range. */
/** @} */
/** @defgroup BLE_GATT_CPF_FORMATS Characteristic Presentation Formats
* @note Found at http://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorViewer.aspx?u=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml
* @{ */
#define BLE_GATT_CPF_FORMAT_RFU 0x00 /**< Reserved For Future Use. */
#define BLE_GATT_CPF_FORMAT_BOOLEAN 0x01 /**< Boolean. */
#define BLE_GATT_CPF_FORMAT_2BIT 0x02 /**< Unsigned 2-bit integer. */
#define BLE_GATT_CPF_FORMAT_NIBBLE 0x03 /**< Unsigned 4-bit integer. */
#define BLE_GATT_CPF_FORMAT_UINT8 0x04 /**< Unsigned 8-bit integer. */
#define BLE_GATT_CPF_FORMAT_UINT12 0x05 /**< Unsigned 12-bit integer. */
#define BLE_GATT_CPF_FORMAT_UINT16 0x06 /**< Unsigned 16-bit integer. */
#define BLE_GATT_CPF_FORMAT_UINT24 0x07 /**< Unsigned 24-bit integer. */
#define BLE_GATT_CPF_FORMAT_UINT32 0x08 /**< Unsigned 32-bit integer. */
#define BLE_GATT_CPF_FORMAT_UINT48 0x09 /**< Unsigned 48-bit integer. */
#define BLE_GATT_CPF_FORMAT_UINT64 0x0A /**< Unsigned 64-bit integer. */
#define BLE_GATT_CPF_FORMAT_UINT128 0x0B /**< Unsigned 128-bit integer. */
#define BLE_GATT_CPF_FORMAT_SINT8 0x0C /**< Signed 2-bit integer. */
#define BLE_GATT_CPF_FORMAT_SINT12 0x0D /**< Signed 12-bit integer. */
#define BLE_GATT_CPF_FORMAT_SINT16 0x0E /**< Signed 16-bit integer. */
#define BLE_GATT_CPF_FORMAT_SINT24 0x0F /**< Signed 24-bit integer. */
#define BLE_GATT_CPF_FORMAT_SINT32 0x10 /**< Signed 32-bit integer. */
#define BLE_GATT_CPF_FORMAT_SINT48 0x11 /**< Signed 48-bit integer. */
#define BLE_GATT_CPF_FORMAT_SINT64 0x12 /**< Signed 64-bit integer. */
#define BLE_GATT_CPF_FORMAT_SINT128 0x13 /**< Signed 128-bit integer. */
#define BLE_GATT_CPF_FORMAT_FLOAT32 0x14 /**< IEEE-754 32-bit floating point. */
#define BLE_GATT_CPF_FORMAT_FLOAT64 0x15 /**< IEEE-754 64-bit floating point. */
#define BLE_GATT_CPF_FORMAT_SFLOAT 0x16 /**< IEEE-11073 16-bit SFLOAT. */
#define BLE_GATT_CPF_FORMAT_FLOAT 0x17 /**< IEEE-11073 32-bit FLOAT. */
#define BLE_GATT_CPF_FORMAT_DUINT16 0x18 /**< IEEE-20601 format. */
#define BLE_GATT_CPF_FORMAT_UTF8S 0x19 /**< UTF-8 string. */
#define BLE_GATT_CPF_FORMAT_UTF16S 0x1A /**< UTF-16 string. */
#define BLE_GATT_CPF_FORMAT_STRUCT 0x1B /**< Opaque Structure. */
/** @} */
/** @defgroup BLE_GATT_CPF_NAMESPACES GATT Bluetooth Namespaces
* @{
*/
#define BLE_GATT_CPF_NAMESPACE_BTSIG 0x01 /**< Bluetooth SIG defined Namespace. */
#define BLE_GATT_CPF_NAMESPACE_DESCRIPTION_UNKNOWN 0x0000 /**< Namespace Description Unknown. */
/** @} */
/** @} */
/** @addtogroup BLE_GATT_STRUCTURES Structures
* @{ */
/**
* @brief BLE GATT connection configuration parameters, set with @ref sd_ble_cfg_set.
*
* @retval ::NRF_ERROR_INVALID_PARAM att_mtu is smaller than @ref BLE_GATT_ATT_MTU_DEFAULT.
*/
typedef struct
{
uint16_t att_mtu; /**< Maximum size of ATT packet the SoftDevice can send or receive.
The default and minimum value is @ref BLE_GATT_ATT_MTU_DEFAULT.
@mscs
@mmsc{@ref BLE_GATTC_MTU_EXCHANGE}
@mmsc{@ref BLE_GATTS_MTU_EXCHANGE}
@endmscs
*/
} ble_gatt_conn_cfg_t;
/**@brief GATT Characteristic Properties. */
typedef struct
{
/* Standard properties */
uint8_t broadcast :1; /**< Broadcasting of the value permitted. */
uint8_t read :1; /**< Reading the value permitted. */
uint8_t write_wo_resp :1; /**< Writing the value with Write Command permitted. */
uint8_t write :1; /**< Writing the value with Write Request permitted. */
uint8_t notify :1; /**< Notification of the value permitted. */
uint8_t indicate :1; /**< Indications of the value permitted. */
uint8_t auth_signed_wr :1; /**< Writing the value with Signed Write Command permitted. */
} ble_gatt_char_props_t;
/**@brief GATT Characteristic Extended Properties. */
typedef struct
{
/* Extended properties */
uint8_t reliable_wr :1; /**< Writing the value with Queued Write operations permitted. */
uint8_t wr_aux :1; /**< Writing the Characteristic User Description descriptor permitted. */
} ble_gatt_char_ext_props_t;
/** @} */
#ifdef __cplusplus
}
#endif
#endif // BLE_GATT_H__
/** @} */

View File

@ -0,0 +1,715 @@
/*
* Copyright (c) 2011 - 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.
*/
/**
@addtogroup BLE_GATTC Generic Attribute Profile (GATT) Client
@{
@brief Definitions and prototypes for the GATT Client interface.
*/
#ifndef BLE_GATTC_H__
#define BLE_GATTC_H__
#include <stdint.h>
#include "nrf.h"
#include "nrf_svc.h"
#include "nrf_error.h"
#include "ble_ranges.h"
#include "ble_types.h"
#include "ble_err.h"
#include "ble_gatt.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup BLE_GATTC_ENUMERATIONS Enumerations
* @{ */
/**@brief GATTC API SVC numbers. */
enum BLE_GATTC_SVCS
{
SD_BLE_GATTC_PRIMARY_SERVICES_DISCOVER = BLE_GATTC_SVC_BASE, /**< Primary Service Discovery. */
SD_BLE_GATTC_RELATIONSHIPS_DISCOVER, /**< Relationship Discovery. */
SD_BLE_GATTC_CHARACTERISTICS_DISCOVER, /**< Characteristic Discovery. */
SD_BLE_GATTC_DESCRIPTORS_DISCOVER, /**< Characteristic Descriptor Discovery. */
SD_BLE_GATTC_ATTR_INFO_DISCOVER, /**< Attribute Information Discovery. */
SD_BLE_GATTC_CHAR_VALUE_BY_UUID_READ, /**< Read Characteristic Value by UUID. */
SD_BLE_GATTC_READ, /**< Generic read. */
SD_BLE_GATTC_CHAR_VALUES_READ, /**< Read multiple Characteristic Values. */
SD_BLE_GATTC_WRITE, /**< Generic write. */
SD_BLE_GATTC_HV_CONFIRM, /**< Handle Value Confirmation. */
SD_BLE_GATTC_EXCHANGE_MTU_REQUEST, /**< Exchange MTU Request. */
};
/**
* @brief GATT Client Event IDs.
*/
enum BLE_GATTC_EVTS
{
BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP = BLE_GATTC_EVT_BASE, /**< Primary Service Discovery Response event. \n See @ref ble_gattc_evt_prim_srvc_disc_rsp_t. */
BLE_GATTC_EVT_REL_DISC_RSP, /**< Relationship Discovery Response event. \n See @ref ble_gattc_evt_rel_disc_rsp_t. */
BLE_GATTC_EVT_CHAR_DISC_RSP, /**< Characteristic Discovery Response event. \n See @ref ble_gattc_evt_char_disc_rsp_t. */
BLE_GATTC_EVT_DESC_DISC_RSP, /**< Descriptor Discovery Response event. \n See @ref ble_gattc_evt_desc_disc_rsp_t. */
BLE_GATTC_EVT_ATTR_INFO_DISC_RSP, /**< Attribute Information Response event. \n See @ref ble_gattc_evt_attr_info_disc_rsp_t. */
BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP, /**< Read By UUID Response event. \n See @ref ble_gattc_evt_char_val_by_uuid_read_rsp_t. */
BLE_GATTC_EVT_READ_RSP, /**< Read Response event. \n See @ref ble_gattc_evt_read_rsp_t. */
BLE_GATTC_EVT_CHAR_VALS_READ_RSP, /**< Read multiple Response event. \n See @ref ble_gattc_evt_char_vals_read_rsp_t. */
BLE_GATTC_EVT_WRITE_RSP, /**< Write Response event. \n See @ref ble_gattc_evt_write_rsp_t. */
BLE_GATTC_EVT_HVX, /**< Handle Value Notification or Indication event. \n Confirm indication with @ref sd_ble_gattc_hv_confirm. \n See @ref ble_gattc_evt_hvx_t. */
BLE_GATTC_EVT_EXCHANGE_MTU_RSP, /**< Exchange MTU Response event. \n See @ref ble_gattc_evt_exchange_mtu_rsp_t. */
BLE_GATTC_EVT_TIMEOUT, /**< Timeout event. \n See @ref ble_gattc_evt_timeout_t. */
BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE /**< Write without Response transmission complete. \n See @ref ble_gattc_evt_write_cmd_tx_complete_t. */
};
/** @} */
/** @addtogroup BLE_GATTC_DEFINES Defines
* @{ */
/** @defgroup BLE_ERRORS_GATTC SVC return values specific to GATTC
* @{ */
#define BLE_ERROR_GATTC_PROC_NOT_PERMITTED (NRF_GATTC_ERR_BASE + 0x000) /**< Procedure not Permitted. */
/** @} */
/** @defgroup BLE_GATTC_ATTR_INFO_FORMAT Attribute Information Formats
* @{ */
#define BLE_GATTC_ATTR_INFO_FORMAT_16BIT 1 /**< 16-bit Attribute Information Format. */
#define BLE_GATTC_ATTR_INFO_FORMAT_128BIT 2 /**< 128-bit Attribute Information Format. */
/** @} */
/** @defgroup BLE_GATTC_DEFAULTS GATT Client defaults
* @{ */
#define BLE_GATTC_WRITE_CMD_TX_QUEUE_SIZE_DEFAULT 1 /**< Default number of Write without Response that can be queued for transmission. */
/** @} */
/** @} */
/** @addtogroup BLE_GATTC_STRUCTURES Structures
* @{ */
/**
* @brief BLE GATTC connection configuration parameters, set with @ref sd_ble_cfg_set.
*/
typedef struct
{
uint8_t write_cmd_tx_queue_size; /**< The guaranteed minimum number of Write without Response that can be queued for transmission.
The default value is @ref BLE_GATTC_WRITE_CMD_TX_QUEUE_SIZE_DEFAULT */
} ble_gattc_conn_cfg_t;
/**@brief Operation Handle Range. */
typedef struct
{
uint16_t start_handle; /**< Start Handle. */
uint16_t end_handle; /**< End Handle. */
} ble_gattc_handle_range_t;
/**@brief GATT service. */
typedef struct
{
ble_uuid_t uuid; /**< Service UUID. */
ble_gattc_handle_range_t handle_range; /**< Service Handle Range. */
} ble_gattc_service_t;
/**@brief GATT include. */
typedef struct
{
uint16_t handle; /**< Include Handle. */
ble_gattc_service_t included_srvc; /**< Handle of the included service. */
} ble_gattc_include_t;
/**@brief GATT characteristic. */
typedef struct
{
ble_uuid_t uuid; /**< Characteristic UUID. */
ble_gatt_char_props_t char_props; /**< Characteristic Properties. */
uint8_t char_ext_props : 1; /**< Extended properties present. */
uint16_t handle_decl; /**< Handle of the Characteristic Declaration. */
uint16_t handle_value; /**< Handle of the Characteristic Value. */
} ble_gattc_char_t;
/**@brief GATT descriptor. */
typedef struct
{
uint16_t handle; /**< Descriptor Handle. */
ble_uuid_t uuid; /**< Descriptor UUID. */
} ble_gattc_desc_t;
/**@brief Write Parameters. */
typedef struct
{
uint8_t write_op; /**< Write Operation to be performed, see @ref BLE_GATT_WRITE_OPS. */
uint8_t flags; /**< Flags, see @ref BLE_GATT_EXEC_WRITE_FLAGS. */
uint16_t handle; /**< Handle to the attribute to be written. */
uint16_t offset; /**< Offset in bytes. @note For WRITE_CMD and WRITE_REQ, offset must be 0. */
uint16_t len; /**< Length of data in bytes. */
uint8_t const *p_value; /**< Pointer to the value data. */
} ble_gattc_write_params_t;
/**@brief Attribute Information for 16-bit Attribute UUID. */
typedef struct
{
uint16_t handle; /**< Attribute handle. */
ble_uuid_t uuid; /**< 16-bit Attribute UUID. */
} ble_gattc_attr_info16_t;
/**@brief Attribute Information for 128-bit Attribute UUID. */
typedef struct
{
uint16_t handle; /**< Attribute handle. */
ble_uuid128_t uuid; /**< 128-bit Attribute UUID. */
} ble_gattc_attr_info128_t;
/**@brief Event structure for @ref BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP. */
typedef struct
{
uint16_t count; /**< Service count. */
ble_gattc_service_t services[1]; /**< Service data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
} ble_gattc_evt_prim_srvc_disc_rsp_t;
/**@brief Event structure for @ref BLE_GATTC_EVT_REL_DISC_RSP. */
typedef struct
{
uint16_t count; /**< Include count. */
ble_gattc_include_t includes[1]; /**< Include data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
} ble_gattc_evt_rel_disc_rsp_t;
/**@brief Event structure for @ref BLE_GATTC_EVT_CHAR_DISC_RSP. */
typedef struct
{
uint16_t count; /**< Characteristic count. */
ble_gattc_char_t chars[1]; /**< Characteristic data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
} ble_gattc_evt_char_disc_rsp_t;
/**@brief Event structure for @ref BLE_GATTC_EVT_DESC_DISC_RSP. */
typedef struct
{
uint16_t count; /**< Descriptor count. */
ble_gattc_desc_t descs[1]; /**< Descriptor data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
} ble_gattc_evt_desc_disc_rsp_t;
/**@brief Event structure for @ref BLE_GATTC_EVT_ATTR_INFO_DISC_RSP. */
typedef struct
{
uint16_t count; /**< Attribute count. */
uint8_t format; /**< Attribute information format, see @ref BLE_GATTC_ATTR_INFO_FORMAT. */
union {
ble_gattc_attr_info16_t attr_info16[1]; /**< Attribute information for 16-bit Attribute UUID.
@note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
ble_gattc_attr_info128_t attr_info128[1]; /**< Attribute information for 128-bit Attribute UUID.
@note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
} info; /**< Attribute information union. */
} ble_gattc_evt_attr_info_disc_rsp_t;
/**@brief GATT read by UUID handle value pair. */
typedef struct
{
uint16_t handle; /**< Attribute Handle. */
uint8_t *p_value; /**< Pointer to the Attribute Value, length is available in @ref ble_gattc_evt_char_val_by_uuid_read_rsp_t::value_len. */
} ble_gattc_handle_value_t;
/**@brief Event structure for @ref BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP. */
typedef struct
{
uint16_t count; /**< Handle-Value Pair Count. */
uint16_t value_len; /**< Length of the value in Handle-Value(s) list. */
uint8_t handle_value[1]; /**< Handle-Value(s) list. To iterate through the list use @ref sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter.
@note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
} ble_gattc_evt_char_val_by_uuid_read_rsp_t;
/**@brief Event structure for @ref BLE_GATTC_EVT_READ_RSP. */
typedef struct
{
uint16_t handle; /**< Attribute Handle. */
uint16_t offset; /**< Offset of the attribute data. */
uint16_t len; /**< Attribute data length. */
uint8_t data[1]; /**< Attribute data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
} ble_gattc_evt_read_rsp_t;
/**@brief Event structure for @ref BLE_GATTC_EVT_CHAR_VALS_READ_RSP. */
typedef struct
{
uint16_t len; /**< Concatenated Attribute values length. */
uint8_t values[1]; /**< Attribute values. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
} ble_gattc_evt_char_vals_read_rsp_t;
/**@brief Event structure for @ref BLE_GATTC_EVT_WRITE_RSP. */
typedef struct
{
uint16_t handle; /**< Attribute Handle. */
uint8_t write_op; /**< Type of write operation, see @ref BLE_GATT_WRITE_OPS. */
uint16_t offset; /**< Data offset. */
uint16_t len; /**< Data length. */
uint8_t data[1]; /**< Data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
} ble_gattc_evt_write_rsp_t;
/**@brief Event structure for @ref BLE_GATTC_EVT_HVX. */
typedef struct
{
uint16_t handle; /**< Handle to which the HVx operation applies. */
uint8_t type; /**< Indication or Notification, see @ref BLE_GATT_HVX_TYPES. */
uint16_t len; /**< Attribute data length. */
uint8_t data[1]; /**< Attribute data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
} ble_gattc_evt_hvx_t;
/**@brief Event structure for @ref BLE_GATTC_EVT_EXCHANGE_MTU_RSP. */
typedef struct
{
uint16_t server_rx_mtu; /**< Server RX MTU size. */
} ble_gattc_evt_exchange_mtu_rsp_t;
/**@brief Event structure for @ref BLE_GATTC_EVT_TIMEOUT. */
typedef struct
{
uint8_t src; /**< Timeout source, see @ref BLE_GATT_TIMEOUT_SOURCES. */
} ble_gattc_evt_timeout_t;
/**@brief Event structure for @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE. */
typedef struct
{
uint8_t count; /**< Number of write without response transmissions completed. */
} ble_gattc_evt_write_cmd_tx_complete_t;
/**@brief GATTC event structure. */
typedef struct
{
uint16_t conn_handle; /**< Connection Handle on which event occurred. */
uint16_t gatt_status; /**< GATT status code for the operation, see @ref BLE_GATT_STATUS_CODES. */
uint16_t error_handle; /**< In case of error: The handle causing the error. In all other cases @ref BLE_GATT_HANDLE_INVALID. */
union
{
ble_gattc_evt_prim_srvc_disc_rsp_t prim_srvc_disc_rsp; /**< Primary Service Discovery Response Event Parameters. */
ble_gattc_evt_rel_disc_rsp_t rel_disc_rsp; /**< Relationship Discovery Response Event Parameters. */
ble_gattc_evt_char_disc_rsp_t char_disc_rsp; /**< Characteristic Discovery Response Event Parameters. */
ble_gattc_evt_desc_disc_rsp_t desc_disc_rsp; /**< Descriptor Discovery Response Event Parameters. */
ble_gattc_evt_char_val_by_uuid_read_rsp_t char_val_by_uuid_read_rsp; /**< Characteristic Value Read by UUID Response Event Parameters. */
ble_gattc_evt_read_rsp_t read_rsp; /**< Read Response Event Parameters. */
ble_gattc_evt_char_vals_read_rsp_t char_vals_read_rsp; /**< Characteristic Values Read Response Event Parameters. */
ble_gattc_evt_write_rsp_t write_rsp; /**< Write Response Event Parameters. */
ble_gattc_evt_hvx_t hvx; /**< Handle Value Notification/Indication Event Parameters. */
ble_gattc_evt_exchange_mtu_rsp_t exchange_mtu_rsp; /**< Exchange MTU Response Event Parameters. */
ble_gattc_evt_timeout_t timeout; /**< Timeout Event Parameters. */
ble_gattc_evt_attr_info_disc_rsp_t attr_info_disc_rsp; /**< Attribute Information Discovery Event Parameters. */
ble_gattc_evt_write_cmd_tx_complete_t write_cmd_tx_complete; /**< Write without Response transmission complete Event Parameters. */
} params; /**< Event Parameters. @note Only valid if @ref gatt_status == @ref BLE_GATT_STATUS_SUCCESS. */
} ble_gattc_evt_t;
/** @} */
/** @addtogroup BLE_GATTC_FUNCTIONS Functions
* @{ */
/**@brief Initiate or continue a GATT Primary Service Discovery procedure.
*
* @details This function initiates or resumes a Primary Service discovery procedure, starting from the supplied handle.
* If the last service has not been reached, this function must be called again with an updated start handle value to continue the search.
*
* @note If any of the discovered services have 128-bit UUIDs which are not present in the table provided to ble_vs_uuids_assign, a UUID structure with
* type @ref BLE_UUID_TYPE_UNKNOWN will be received in the corresponding event.
*
* @events
* @event{@ref BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP}
* @endevents
*
* @mscs
* @mmsc{@ref BLE_GATTC_PRIM_SRVC_DISC_MSC}
* @endmscs
*
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
* @param[in] start_handle Handle to start searching from.
* @param[in] p_srvc_uuid Pointer to the service UUID to be found. If it is NULL, all primary services will be returned.
*
* @retval ::NRF_SUCCESS Successfully started or resumed the Primary Service Discovery procedure.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
* @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection.
*/
SVCALL(SD_BLE_GATTC_PRIMARY_SERVICES_DISCOVER, uint32_t, sd_ble_gattc_primary_services_discover(uint16_t conn_handle, uint16_t start_handle, ble_uuid_t const *p_srvc_uuid));
/**@brief Initiate or continue a GATT Relationship Discovery procedure.
*
* @details This function initiates or resumes the Find Included Services sub-procedure. If the last included service has not been reached,
* this must be called again with an updated handle range to continue the search.
*
* @events
* @event{@ref BLE_GATTC_EVT_REL_DISC_RSP}
* @endevents
*
* @mscs
* @mmsc{@ref BLE_GATTC_REL_DISC_MSC}
* @endmscs
*
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
* @param[in] p_handle_range A pointer to the range of handles of the Service to perform this procedure on.
*
* @retval ::NRF_SUCCESS Successfully started or resumed the Relationship Discovery procedure.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
* @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection.
*/
SVCALL(SD_BLE_GATTC_RELATIONSHIPS_DISCOVER, uint32_t, sd_ble_gattc_relationships_discover(uint16_t conn_handle, ble_gattc_handle_range_t const *p_handle_range));
/**@brief Initiate or continue a GATT Characteristic Discovery procedure.
*
* @details This function initiates or resumes a Characteristic discovery procedure. If the last Characteristic has not been reached,
* this must be called again with an updated handle range to continue the discovery.
*
* @note If any of the discovered characteristics have 128-bit UUIDs which are not present in the table provided to ble_vs_uuids_assign, a UUID structure with
* type @ref BLE_UUID_TYPE_UNKNOWN will be received in the corresponding event.
*
* @events
* @event{@ref BLE_GATTC_EVT_CHAR_DISC_RSP}
* @endevents
*
* @mscs
* @mmsc{@ref BLE_GATTC_CHAR_DISC_MSC}
* @endmscs
*
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
* @param[in] p_handle_range A pointer to the range of handles of the Service to perform this procedure on.
*
* @retval ::NRF_SUCCESS Successfully started or resumed the Characteristic Discovery procedure.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
* @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection.
*/
SVCALL(SD_BLE_GATTC_CHARACTERISTICS_DISCOVER, uint32_t, sd_ble_gattc_characteristics_discover(uint16_t conn_handle, ble_gattc_handle_range_t const *p_handle_range));
/**@brief Initiate or continue a GATT Characteristic Descriptor Discovery procedure.
*
* @details This function initiates or resumes a Characteristic Descriptor discovery procedure. If the last Descriptor has not been reached,
* this must be called again with an updated handle range to continue the discovery.
*
* @events
* @event{@ref BLE_GATTC_EVT_DESC_DISC_RSP}
* @endevents
*
* @mscs
* @mmsc{@ref BLE_GATTC_DESC_DISC_MSC}
* @endmscs
*
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
* @param[in] p_handle_range A pointer to the range of handles of the Characteristic to perform this procedure on.
*
* @retval ::NRF_SUCCESS Successfully started or resumed the Descriptor Discovery procedure.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
* @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection.
*/
SVCALL(SD_BLE_GATTC_DESCRIPTORS_DISCOVER, uint32_t, sd_ble_gattc_descriptors_discover(uint16_t conn_handle, ble_gattc_handle_range_t const *p_handle_range));
/**@brief Initiate or continue a GATT Read using Characteristic UUID procedure.
*
* @details This function initiates or resumes a Read using Characteristic UUID procedure. If the last Characteristic has not been reached,
* this must be called again with an updated handle range to continue the discovery.
*
* @events
* @event{@ref BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP}
* @endevents
*
* @mscs
* @mmsc{@ref BLE_GATTC_READ_UUID_MSC}
* @endmscs
*
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
* @param[in] p_uuid Pointer to a Characteristic value UUID to read.
* @param[in] p_handle_range A pointer to the range of handles to perform this procedure on.
*
* @retval ::NRF_SUCCESS Successfully started or resumed the Read using Characteristic UUID procedure.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
* @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection.
*/
SVCALL(SD_BLE_GATTC_CHAR_VALUE_BY_UUID_READ, uint32_t, sd_ble_gattc_char_value_by_uuid_read(uint16_t conn_handle, ble_uuid_t const *p_uuid, ble_gattc_handle_range_t const *p_handle_range));
/**@brief Initiate or continue a GATT Read (Long) Characteristic or Descriptor procedure.
*
* @details This function initiates or resumes a GATT Read (Long) Characteristic or Descriptor procedure. If the Characteristic or Descriptor
* to be read is longer than ATT_MTU - 1, this function must be called multiple times with appropriate offset to read the
* complete value.
*
* @events
* @event{@ref BLE_GATTC_EVT_READ_RSP}
* @endevents
*
* @mscs
* @mmsc{@ref BLE_GATTC_VALUE_READ_MSC}
* @endmscs
*
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
* @param[in] handle The handle of the attribute to be read.
* @param[in] offset Offset into the attribute value to be read.
*
* @retval ::NRF_SUCCESS Successfully started or resumed the Read (Long) procedure.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
* @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection.
*/
SVCALL(SD_BLE_GATTC_READ, uint32_t, sd_ble_gattc_read(uint16_t conn_handle, uint16_t handle, uint16_t offset));
/**@brief Initiate a GATT Read Multiple Characteristic Values procedure.
*
* @details This function initiates a GATT Read Multiple Characteristic Values procedure.
*
* @events
* @event{@ref BLE_GATTC_EVT_CHAR_VALS_READ_RSP}
* @endevents
*
* @mscs
* @mmsc{@ref BLE_GATTC_READ_MULT_MSC}
* @endmscs
*
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
* @param[in] p_handles A pointer to the handle(s) of the attribute(s) to be read.
* @param[in] handle_count The number of handles in p_handles.
*
* @retval ::NRF_SUCCESS Successfully started the Read Multiple Characteristic Values procedure.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
* @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection.
*/
SVCALL(SD_BLE_GATTC_CHAR_VALUES_READ, uint32_t, sd_ble_gattc_char_values_read(uint16_t conn_handle, uint16_t const *p_handles, uint16_t handle_count));
/**@brief Perform a Write (Characteristic Value or Descriptor, with or without response, signed or not, long or reliable) procedure.
*
* @details This function can perform all write procedures described in GATT.
*
* @note Only one write with response procedure can be ongoing per connection at a time.
* If the application tries to write with response while another write with response procedure is ongoing,
* the function call will return @ref NRF_ERROR_BUSY.
* A @ref BLE_GATTC_EVT_WRITE_RSP event will be issued as soon as the write response arrives from the peer.
*
* @note The number of Write without Response that can be queued is configured by @ref ble_gattc_conn_cfg_t::write_cmd_tx_queue_size
* When the queue is full, the function call will return @ref NRF_ERROR_RESOURCES.
* A @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE event will be issued as soon as the transmission of the write without response is complete.
*
* @note The application can keep track of the available queue element count for writes without responses by following the procedure below:
* - Store initial queue element count in a variable.
* - Decrement the variable, which stores the currently available queue element count, by one when a call to this function returns @ref NRF_SUCCESS.
* - Increment the variable, which stores the current available queue element count, by the count variable in @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE event.
*
* @events
* @event{@ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE, Write without response transmission complete.}
* @event{@ref BLE_GATTC_EVT_WRITE_RSP, Write response received from the peer.}
* @endevents
*
* @mscs
* @mmsc{@ref BLE_GATTC_VALUE_WRITE_WITHOUT_RESP_MSC}
* @mmsc{@ref BLE_GATTC_VALUE_WRITE_MSC}
* @mmsc{@ref BLE_GATTC_VALUE_LONG_WRITE_MSC}
* @mmsc{@ref BLE_GATTC_VALUE_RELIABLE_WRITE_MSC}
* @endmscs
*
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
* @param[in] p_write_params A pointer to a write parameters structure.
*
* @retval ::NRF_SUCCESS Successfully started the Write procedure.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
* @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied.
* @retval ::NRF_ERROR_BUSY For write with response, procedure already in progress. Wait for a @ref BLE_GATTC_EVT_WRITE_RSP event and retry.
* @retval ::NRF_ERROR_RESOURCES Too many writes without responses queued.
* Wait for a @ref BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE event and retry.
* @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection.
*/
SVCALL(SD_BLE_GATTC_WRITE, uint32_t, sd_ble_gattc_write(uint16_t conn_handle, ble_gattc_write_params_t const *p_write_params));
/**@brief Send a Handle Value Confirmation to the GATT Server.
*
* @mscs
* @mmsc{@ref BLE_GATTC_HVI_MSC}
* @endmscs
*
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
* @param[in] handle The handle of the attribute in the indication.
*
* @retval ::NRF_SUCCESS Successfully queued the Handle Value Confirmation for transmission.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State or no Indication pending to be confirmed.
* @retval ::BLE_ERROR_INVALID_ATTR_HANDLE Invalid attribute handle.
* @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection.
*/
SVCALL(SD_BLE_GATTC_HV_CONFIRM, uint32_t, sd_ble_gattc_hv_confirm(uint16_t conn_handle, uint16_t handle));
/**@brief Discovers information about a range of attributes on a GATT server.
*
* @events
* @event{@ref BLE_GATTC_EVT_ATTR_INFO_DISC_RSP, Generated when information about a range of attributes has been received.}
* @endevents
*
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
* @param[in] p_handle_range The range of handles to request information about.
*
* @retval ::NRF_SUCCESS Successfully started an attribute information discovery procedure.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle.
* @retval ::NRF_ERROR_INVALID_STATE Invalid connection state
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
* @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection.
*/
SVCALL(SD_BLE_GATTC_ATTR_INFO_DISCOVER, uint32_t, sd_ble_gattc_attr_info_discover(uint16_t conn_handle, ble_gattc_handle_range_t const * p_handle_range));
/**@brief Start an ATT_MTU exchange by sending an Exchange MTU Request to the server.
*
* @details The SoftDevice sets ATT_MTU to the minimum of:
* - The Client RX MTU value, and
* - The Server RX MTU value from @ref BLE_GATTC_EVT_EXCHANGE_MTU_RSP.
*
* However, the SoftDevice never sets ATT_MTU lower than @ref BLE_GATT_ATT_MTU_DEFAULT.
*
* @events
* @event{@ref BLE_GATTC_EVT_EXCHANGE_MTU_RSP}
* @endevents
*
* @mscs
* @mmsc{@ref BLE_GATTC_MTU_EXCHANGE}
* @endmscs
*
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
* @param[in] client_rx_mtu Client RX MTU size.
* - The minimum value is @ref BLE_GATT_ATT_MTU_DEFAULT.
* - The maximum value is @ref ble_gatt_conn_cfg_t::att_mtu in the connection configuration
used for this connection.
* - The value must be equal to Server RX MTU size given in @ref sd_ble_gatts_exchange_mtu_reply
* if an ATT_MTU exchange has already been performed in the other direction.
*
* @retval ::NRF_SUCCESS Successfully sent request to the server.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle.
* @retval ::NRF_ERROR_INVALID_STATE Invalid connection state or an ATT_MTU exchange was already requested once.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid Client RX MTU size supplied.
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
* @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection.
*/
SVCALL(SD_BLE_GATTC_EXCHANGE_MTU_REQUEST, uint32_t, sd_ble_gattc_exchange_mtu_request(uint16_t conn_handle, uint16_t client_rx_mtu));
/**@brief Iterate through Handle-Value(s) list in @ref BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP event.
*
* @param[in] p_gattc_evt Pointer to event buffer containing @ref BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP event.
* @note If the buffer contains different event, behavior is undefined.
* @param[in,out] p_iter Iterator, points to @ref ble_gattc_handle_value_t structure that will be filled in with
* the next Handle-Value pair in each iteration. If the function returns other than
* @ref NRF_SUCCESS, it will not be changed.
* - To start iteration, initialize the structure to zero.
* - To continue, pass the value from previous iteration.
*
* \code
* ble_gattc_handle_value_t iter;
* memset(&iter, 0, sizeof(ble_gattc_handle_value_t));
* while (sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter(&ble_evt.evt.gattc_evt, &iter) == NRF_SUCCESS)
* {
* app_handle = iter.handle;
* memcpy(app_value, iter.p_value, ble_evt.evt.gattc_evt.params.char_val_by_uuid_read_rsp.value_len);
* }
* \endcode
*
* @retval ::NRF_SUCCESS Successfully retrieved the next Handle-Value pair.
* @retval ::NRF_ERROR_NOT_FOUND No more Handle-Value pairs available in the list.
*/
__STATIC_INLINE uint32_t sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter(ble_gattc_evt_t *p_gattc_evt, ble_gattc_handle_value_t *p_iter);
/** @} */
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE uint32_t sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter(ble_gattc_evt_t *p_gattc_evt, ble_gattc_handle_value_t *p_iter)
{
uint32_t value_len = p_gattc_evt->params.char_val_by_uuid_read_rsp.value_len;
uint8_t *p_first = p_gattc_evt->params.char_val_by_uuid_read_rsp.handle_value;
uint8_t *p_next = p_iter->p_value ? p_iter->p_value + value_len : p_first;
if ((p_next - p_first) / (sizeof(uint16_t) + value_len) < p_gattc_evt->params.char_val_by_uuid_read_rsp.count)
{
p_iter->handle = (uint16_t)p_next[1] << 8 | p_next[0];
p_iter->p_value = p_next + sizeof(uint16_t);
return NRF_SUCCESS;
}
else
{
return NRF_ERROR_NOT_FOUND;
}
}
#endif /* SUPPRESS_INLINE_IMPLEMENTATION */
#ifdef __cplusplus
}
#endif
#endif /* BLE_GATTC_H__ */
/**
@}
*/

View File

@ -0,0 +1,845 @@
/*
* Copyright (c) 2011 - 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.
*/
/**
@addtogroup BLE_GATTS Generic Attribute Profile (GATT) Server
@{
@brief Definitions and prototypes for the GATTS interface.
*/
#ifndef BLE_GATTS_H__
#define BLE_GATTS_H__
#include <stdint.h>
#include "nrf_svc.h"
#include "nrf_error.h"
#include "ble_hci.h"
#include "ble_ranges.h"
#include "ble_types.h"
#include "ble_err.h"
#include "ble_gatt.h"
#include "ble_gap.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup BLE_GATTS_ENUMERATIONS Enumerations
* @{ */
/**
* @brief GATTS API SVC numbers.
*/
enum BLE_GATTS_SVCS
{
SD_BLE_GATTS_SERVICE_ADD = BLE_GATTS_SVC_BASE, /**< Add a service. */
SD_BLE_GATTS_INCLUDE_ADD, /**< Add an included service. */
SD_BLE_GATTS_CHARACTERISTIC_ADD, /**< Add a characteristic. */
SD_BLE_GATTS_DESCRIPTOR_ADD, /**< Add a generic attribute. */
SD_BLE_GATTS_VALUE_SET, /**< Set an attribute value. */
SD_BLE_GATTS_VALUE_GET, /**< Get an attribute value. */
SD_BLE_GATTS_HVX, /**< Handle Value Notification or Indication. */
SD_BLE_GATTS_SERVICE_CHANGED, /**< Perform a Service Changed Indication to one or more peers. */
SD_BLE_GATTS_RW_AUTHORIZE_REPLY, /**< Reply to an authorization request for a read or write operation on one or more attributes. */
SD_BLE_GATTS_SYS_ATTR_SET, /**< Set the persistent system attributes for a connection. */
SD_BLE_GATTS_SYS_ATTR_GET, /**< Retrieve the persistent system attributes. */
SD_BLE_GATTS_INITIAL_USER_HANDLE_GET, /**< Retrieve the first valid user handle. */
SD_BLE_GATTS_ATTR_GET, /**< Retrieve the UUID and/or metadata of an attribute. */
SD_BLE_GATTS_EXCHANGE_MTU_REPLY /**< Reply to Exchange MTU Request. */
};
/**
* @brief GATT Server Event IDs.
*/
enum BLE_GATTS_EVTS
{
BLE_GATTS_EVT_WRITE = BLE_GATTS_EVT_BASE, /**< Write operation performed. \n See @ref ble_gatts_evt_write_t. */
BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST, /**< Read/Write Authorization request. \n Reply with @ref sd_ble_gatts_rw_authorize_reply. \n See @ref ble_gatts_evt_rw_authorize_request_t. */
BLE_GATTS_EVT_SYS_ATTR_MISSING, /**< A persistent system attribute access is pending. \n Respond with @ref sd_ble_gatts_sys_attr_set. \n See @ref ble_gatts_evt_sys_attr_missing_t. */
BLE_GATTS_EVT_HVC, /**< Handle Value Confirmation. \n See @ref ble_gatts_evt_hvc_t. */
BLE_GATTS_EVT_SC_CONFIRM, /**< Service Changed Confirmation. \n No additional event structure applies. */
BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST, /**< Exchange MTU Request. \n Reply with @ref sd_ble_gatts_exchange_mtu_reply. \n See @ref ble_gatts_evt_exchange_mtu_request_t. */
BLE_GATTS_EVT_TIMEOUT, /**< Peer failed to respond to an ATT request in time. \n See @ref ble_gatts_evt_timeout_t. */
BLE_GATTS_EVT_HVN_TX_COMPLETE /**< Handle Value Notification transmission complete. \n See @ref ble_gatts_evt_hvn_tx_complete_t. */
};
/**@brief GATTS Configuration IDs.
*
* IDs that uniquely identify a GATTS configuration.
*/
enum BLE_GATTS_CFGS
{
BLE_GATTS_CFG_SERVICE_CHANGED = BLE_GATTS_CFG_BASE, /**< Service changed configuration. */
BLE_GATTS_CFG_ATTR_TAB_SIZE, /**< Attribute table size configuration. */
};
/** @} */
/** @addtogroup BLE_GATTS_DEFINES Defines
* @{ */
/** @defgroup BLE_ERRORS_GATTS SVC return values specific to GATTS
* @{ */
#define BLE_ERROR_GATTS_INVALID_ATTR_TYPE (NRF_GATTS_ERR_BASE + 0x000) /**< Invalid attribute type. */
#define BLE_ERROR_GATTS_SYS_ATTR_MISSING (NRF_GATTS_ERR_BASE + 0x001) /**< System Attributes missing. */
/** @} */
/** @defgroup BLE_GATTS_ATTR_LENS_MAX Maximum attribute lengths
* @{ */
#define BLE_GATTS_FIX_ATTR_LEN_MAX (510) /**< Maximum length for fixed length Attribute Values. */
#define BLE_GATTS_VAR_ATTR_LEN_MAX (512) /**< Maximum length for variable length Attribute Values. */
/** @} */
/** @defgroup BLE_GATTS_SRVC_TYPES GATT Server Service Types
* @{ */
#define BLE_GATTS_SRVC_TYPE_INVALID 0x00 /**< Invalid Service Type. */
#define BLE_GATTS_SRVC_TYPE_PRIMARY 0x01 /**< Primary Service. */
#define BLE_GATTS_SRVC_TYPE_SECONDARY 0x02 /**< Secondary Type. */
/** @} */
/** @defgroup BLE_GATTS_ATTR_TYPES GATT Server Attribute Types
* @{ */
#define BLE_GATTS_ATTR_TYPE_INVALID 0x00 /**< Invalid Attribute Type. */
#define BLE_GATTS_ATTR_TYPE_PRIM_SRVC_DECL 0x01 /**< Primary Service Declaration. */
#define BLE_GATTS_ATTR_TYPE_SEC_SRVC_DECL 0x02 /**< Secondary Service Declaration. */
#define BLE_GATTS_ATTR_TYPE_INC_DECL 0x03 /**< Include Declaration. */
#define BLE_GATTS_ATTR_TYPE_CHAR_DECL 0x04 /**< Characteristic Declaration. */
#define BLE_GATTS_ATTR_TYPE_CHAR_VAL 0x05 /**< Characteristic Value. */
#define BLE_GATTS_ATTR_TYPE_DESC 0x06 /**< Descriptor. */
#define BLE_GATTS_ATTR_TYPE_OTHER 0x07 /**< Other, non-GATT specific type. */
/** @} */
/** @defgroup BLE_GATTS_OPS GATT Server Operations
* @{ */
#define BLE_GATTS_OP_INVALID 0x00 /**< Invalid Operation. */
#define BLE_GATTS_OP_WRITE_REQ 0x01 /**< Write Request. */
#define BLE_GATTS_OP_WRITE_CMD 0x02 /**< Write Command. */
#define BLE_GATTS_OP_SIGN_WRITE_CMD 0x03 /**< Signed Write Command. */
#define BLE_GATTS_OP_PREP_WRITE_REQ 0x04 /**< Prepare Write Request. */
#define BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL 0x05 /**< Execute Write Request: Cancel all prepared writes. */
#define BLE_GATTS_OP_EXEC_WRITE_REQ_NOW 0x06 /**< Execute Write Request: Immediately execute all prepared writes. */
/** @} */
/** @defgroup BLE_GATTS_VLOCS GATT Value Locations
* @{ */
#define BLE_GATTS_VLOC_INVALID 0x00 /**< Invalid Location. */
#define BLE_GATTS_VLOC_STACK 0x01 /**< Attribute Value is located in stack memory, no user memory is required. */
#define BLE_GATTS_VLOC_USER 0x02 /**< Attribute Value is located in user memory. This requires the user to maintain a valid buffer through the lifetime of the attribute, since the stack
will read and write directly to the memory using the pointer provided in the APIs. There are no alignment requirements for the buffer. */
/** @} */
/** @defgroup BLE_GATTS_AUTHORIZE_TYPES GATT Server Authorization Types
* @{ */
#define BLE_GATTS_AUTHORIZE_TYPE_INVALID 0x00 /**< Invalid Type. */
#define BLE_GATTS_AUTHORIZE_TYPE_READ 0x01 /**< Authorize a Read Operation. */
#define BLE_GATTS_AUTHORIZE_TYPE_WRITE 0x02 /**< Authorize a Write Request Operation. */
/** @} */
/** @defgroup BLE_GATTS_SYS_ATTR_FLAGS System Attribute Flags
* @{ */
#define BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS (1 << 0) /**< Restrict system attributes to system services only. */
#define BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS (1 << 1) /**< Restrict system attributes to user services only. */
/** @} */
/** @defgroup BLE_GATTS_SERVICE_CHANGED Service Changed Inclusion Values
* @{
*/
#define BLE_GATTS_SERVICE_CHANGED_DEFAULT (1) /**< Default is to include the Service Changed characteristic in the Attribute Table. */
/** @} */
/** @defgroup BLE_GATTS_ATTR_TAB_SIZE Attribute Table size
* @{
*/
#define BLE_GATTS_ATTR_TAB_SIZE_MIN (248) /**< Minimum Attribute Table size */
#define BLE_GATTS_ATTR_TAB_SIZE_DEFAULT (1408) /**< Default Attribute Table size. */
/** @} */
/** @defgroup BLE_GATTS_DEFAULTS GATT Server defaults
* @{
*/
#define BLE_GATTS_HVN_TX_QUEUE_SIZE_DEFAULT 1 /**< Default number of Handle Value Notifications that can be queued for transmission. */
/** @} */
/** @} */
/** @addtogroup BLE_GATTS_STRUCTURES Structures
* @{ */
/**
* @brief BLE GATTS connection configuration parameters, set with @ref sd_ble_cfg_set.
*/
typedef struct
{
uint8_t hvn_tx_queue_size; /**< Minimum guaranteed number of Handle Value Notifications that can be queued for transmission.
The default value is @ref BLE_GATTS_HVN_TX_QUEUE_SIZE_DEFAULT */
} ble_gatts_conn_cfg_t;
/**@brief Attribute metadata. */
typedef struct
{
ble_gap_conn_sec_mode_t read_perm; /**< Read permissions. */
ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */
uint8_t vlen :1; /**< Variable length attribute. */
uint8_t vloc :2; /**< Value location, see @ref BLE_GATTS_VLOCS.*/
uint8_t rd_auth :1; /**< Read authorization and value will be requested from the application on every read operation. */
uint8_t wr_auth :1; /**< Write authorization will be requested from the application on every Write Request operation (but not Write Command). */
} ble_gatts_attr_md_t;
/**@brief GATT Attribute. */
typedef struct
{
ble_uuid_t const *p_uuid; /**< Pointer to the attribute UUID. */
ble_gatts_attr_md_t const *p_attr_md; /**< Pointer to the attribute metadata structure. */
uint16_t init_len; /**< Initial attribute value length in bytes. */
uint16_t init_offs; /**< Initial attribute value offset in bytes. If different from zero, the first init_offs bytes of the attribute value will be left uninitialized. */
uint16_t max_len; /**< Maximum attribute value length in bytes, see @ref BLE_GATTS_ATTR_LENS_MAX for maximum values. */
uint8_t *p_value; /**< Pointer to the attribute data. Please note that if the @ref BLE_GATTS_VLOC_USER value location is selected in the attribute metadata, this will have to point to a buffer
that remains valid through the lifetime of the attribute. This excludes usage of automatic variables that may go out of scope or any other temporary location.
The stack may access that memory directly without the application's knowledge. For writable characteristics, this value must not be a location in flash memory.*/
} ble_gatts_attr_t;
/**@brief GATT Attribute Value. */
typedef struct
{
uint16_t len; /**< Length in bytes to be written or read. Length in bytes written or read after successful return.*/
uint16_t offset; /**< Attribute value offset. */
uint8_t *p_value; /**< Pointer to where value is stored or will be stored.
If value is stored in user memory, only the attribute length is updated when p_value == NULL.
Set to NULL when reading to obtain the complete length of the attribute value */
} ble_gatts_value_t;
/**@brief GATT Characteristic Presentation Format. */
typedef struct
{
uint8_t format; /**< Format of the value, see @ref BLE_GATT_CPF_FORMATS. */
int8_t exponent; /**< Exponent for integer data types. */
uint16_t unit; /**< Unit from Bluetooth Assigned Numbers. */
uint8_t name_space; /**< Namespace from Bluetooth Assigned Numbers, see @ref BLE_GATT_CPF_NAMESPACES. */
uint16_t desc; /**< Namespace description from Bluetooth Assigned Numbers, see @ref BLE_GATT_CPF_NAMESPACES. */
} ble_gatts_char_pf_t;
/**@brief GATT Characteristic metadata. */
typedef struct
{
ble_gatt_char_props_t char_props; /**< Characteristic Properties. */
ble_gatt_char_ext_props_t char_ext_props; /**< Characteristic Extended Properties. */
uint8_t const *p_char_user_desc; /**< Pointer to a UTF-8 encoded string (non-NULL terminated), NULL if the descriptor is not required. */
uint16_t char_user_desc_max_size; /**< The maximum size in bytes of the user description descriptor. */
uint16_t char_user_desc_size; /**< The size of the user description, must be smaller or equal to char_user_desc_max_size. */
ble_gatts_char_pf_t const *p_char_pf; /**< Pointer to a presentation format structure or NULL if the CPF descriptor is not required. */
ble_gatts_attr_md_t const *p_user_desc_md; /**< Attribute metadata for the User Description descriptor, or NULL for default values. */
ble_gatts_attr_md_t const *p_cccd_md; /**< Attribute metadata for the Client Characteristic Configuration Descriptor, or NULL for default values. */
ble_gatts_attr_md_t const *p_sccd_md; /**< Attribute metadata for the Server Characteristic Configuration Descriptor, or NULL for default values. */
} ble_gatts_char_md_t;
/**@brief GATT Characteristic Definition Handles. */
typedef struct
{
uint16_t value_handle; /**< Handle to the characteristic value. */
uint16_t user_desc_handle; /**< Handle to the User Description descriptor, or @ref BLE_GATT_HANDLE_INVALID if not present. */
uint16_t cccd_handle; /**< Handle to the Client Characteristic Configuration Descriptor, or @ref BLE_GATT_HANDLE_INVALID if not present. */
uint16_t sccd_handle; /**< Handle to the Server Characteristic Configuration Descriptor, or @ref BLE_GATT_HANDLE_INVALID if not present. */
} ble_gatts_char_handles_t;
/**@brief GATT HVx parameters. */
typedef struct
{
uint16_t handle; /**< Characteristic Value Handle. */
uint8_t type; /**< Indication or Notification, see @ref BLE_GATT_HVX_TYPES. */
uint16_t offset; /**< Offset within the attribute value. */
uint16_t *p_len; /**< Length in bytes to be written, length in bytes written after return. */
uint8_t const *p_data; /**< Actual data content, use NULL to use the current attribute value. */
} ble_gatts_hvx_params_t;
/**@brief GATT Authorization parameters. */
typedef struct
{
uint16_t gatt_status; /**< GATT status code for the operation, see @ref BLE_GATT_STATUS_CODES. */
uint8_t update : 1; /**< If set, data supplied in p_data will be used to update the attribute value.
Please note that for @ref BLE_GATTS_AUTHORIZE_TYPE_WRITE operations this bit must always be set,
as the data to be written needs to be stored and later provided by the application. */
uint16_t offset; /**< Offset of the attribute value being updated. */
uint16_t len; /**< Length in bytes of the value in p_data pointer, see @ref BLE_GATTS_ATTR_LENS_MAX. */
uint8_t const *p_data; /**< Pointer to new value used to update the attribute value. */
} ble_gatts_authorize_params_t;
/**@brief GATT Read or Write Authorize Reply parameters. */
typedef struct
{
uint8_t type; /**< Type of authorize operation, see @ref BLE_GATTS_AUTHORIZE_TYPES. */
union {
ble_gatts_authorize_params_t read; /**< Read authorization parameters. */
ble_gatts_authorize_params_t write; /**< Write authorization parameters. */
} params; /**< Reply Parameters. */
} ble_gatts_rw_authorize_reply_params_t;
/**@brief Service Changed Inclusion configuration parameters, set with @ref sd_ble_cfg_set. */
typedef struct
{
uint8_t service_changed : 1; /**< If 1, include the Service Changed characteristic in the Attribute Table. Default is @ref BLE_GATTS_SERVICE_CHANGED_DEFAULT. */
} ble_gatts_cfg_service_changed_t;
/**@brief Attribute table size configuration parameters, set with @ref sd_ble_cfg_set.
*
* @retval ::NRF_ERROR_INVALID_LENGTH One or more of the following is true:
* - The specified Attribute Table size is too small.
* The minimum acceptable size is defined by @ref BLE_GATTS_ATTR_TAB_SIZE_MIN.
* - The specified Attribute Table size is not a multiple of 4.
*/
typedef struct
{
uint32_t attr_tab_size; /**< Attribute table size. Default is @ref BLE_GATTS_ATTR_TAB_SIZE_DEFAULT, minimum is @ref BLE_GATTS_ATTR_TAB_SIZE_MIN. */
} ble_gatts_cfg_attr_tab_size_t;
/**@brief Config structure for GATTS configurations. */
typedef union
{
ble_gatts_cfg_service_changed_t service_changed; /**< Include service changed characteristic, cfg_id is @ref BLE_GATTS_CFG_SERVICE_CHANGED. */
ble_gatts_cfg_attr_tab_size_t attr_tab_size; /**< Attribute table size, cfg_id is @ref BLE_GATTS_CFG_ATTR_TAB_SIZE. */
} ble_gatts_cfg_t;
/**@brief Event structure for @ref BLE_GATTS_EVT_WRITE. */
typedef struct
{
uint16_t handle; /**< Attribute Handle. */
ble_uuid_t uuid; /**< Attribute UUID. */
uint8_t op; /**< Type of write operation, see @ref BLE_GATTS_OPS. */
uint8_t auth_required; /**< Writing operation deferred due to authorization requirement. Application may use @ref sd_ble_gatts_value_set to finalize the writing operation. */
uint16_t offset; /**< Offset for the write operation. */
uint16_t len; /**< Length of the received data. */
uint8_t data[1]; /**< Received data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
} ble_gatts_evt_write_t;
/**@brief Event substructure for authorized read requests, see @ref ble_gatts_evt_rw_authorize_request_t. */
typedef struct
{
uint16_t handle; /**< Attribute Handle. */
ble_uuid_t uuid; /**< Attribute UUID. */
uint16_t offset; /**< Offset for the read operation. */
} ble_gatts_evt_read_t;
/**@brief Event structure for @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST. */
typedef struct
{
uint8_t type; /**< Type of authorize operation, see @ref BLE_GATTS_AUTHORIZE_TYPES. */
union {
ble_gatts_evt_read_t read; /**< Attribute Read Parameters. */
ble_gatts_evt_write_t write; /**< Attribute Write Parameters. */
} request; /**< Request Parameters. */
} ble_gatts_evt_rw_authorize_request_t;
/**@brief Event structure for @ref BLE_GATTS_EVT_SYS_ATTR_MISSING. */
typedef struct
{
uint8_t hint; /**< Hint (currently unused). */
} ble_gatts_evt_sys_attr_missing_t;
/**@brief Event structure for @ref BLE_GATTS_EVT_HVC. */
typedef struct
{
uint16_t handle; /**< Attribute Handle. */
} ble_gatts_evt_hvc_t;
/**@brief Event structure for @ref BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST. */
typedef struct
{
uint16_t client_rx_mtu; /**< Client RX MTU size. */
} ble_gatts_evt_exchange_mtu_request_t;
/**@brief Event structure for @ref BLE_GATTS_EVT_TIMEOUT. */
typedef struct
{
uint8_t src; /**< Timeout source, see @ref BLE_GATT_TIMEOUT_SOURCES. */
} ble_gatts_evt_timeout_t;
/**@brief Event structure for @ref BLE_GATTS_EVT_HVN_TX_COMPLETE. */
typedef struct
{
uint8_t count; /**< Number of notification transmissions completed. */
} ble_gatts_evt_hvn_tx_complete_t;
/**@brief GATTS event structure. */
typedef struct
{
uint16_t conn_handle; /**< Connection Handle on which the event occurred. */
union
{
ble_gatts_evt_write_t write; /**< Write Event Parameters. */
ble_gatts_evt_rw_authorize_request_t authorize_request; /**< Read or Write Authorize Request Parameters. */
ble_gatts_evt_sys_attr_missing_t sys_attr_missing; /**< System attributes missing. */
ble_gatts_evt_hvc_t hvc; /**< Handle Value Confirmation Event Parameters. */
ble_gatts_evt_exchange_mtu_request_t exchange_mtu_request; /**< Exchange MTU Request Event Parameters. */
ble_gatts_evt_timeout_t timeout; /**< Timeout Event. */
ble_gatts_evt_hvn_tx_complete_t hvn_tx_complete; /**< Handle Value Notification transmission complete Event Parameters. */
} params; /**< Event Parameters. */
} ble_gatts_evt_t;
/** @} */
/** @addtogroup BLE_GATTS_FUNCTIONS Functions
* @{ */
/**@brief Add a service declaration to the Attribute Table.
*
* @note Secondary Services are only relevant in the context of the entity that references them, it is therefore forbidden to
* add a secondary service declaration that is not referenced by another service later in the Attribute Table.
*
* @mscs
* @mmsc{@ref BLE_GATTS_ATT_TABLE_POP_MSC}
* @endmscs
*
* @param[in] type Toggles between primary and secondary services, see @ref BLE_GATTS_SRVC_TYPES.
* @param[in] p_uuid Pointer to service UUID.
* @param[out] p_handle Pointer to a 16-bit word where the assigned handle will be stored.
*
* @retval ::NRF_SUCCESS Successfully added a service declaration.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, Vendor Specific UUIDs need to be present in the table.
* @retval ::NRF_ERROR_FORBIDDEN Forbidden value supplied, certain UUIDs are reserved for the stack.
* @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation.
*/
SVCALL(SD_BLE_GATTS_SERVICE_ADD, uint32_t, sd_ble_gatts_service_add(uint8_t type, ble_uuid_t const *p_uuid, uint16_t *p_handle));
/**@brief Add an include declaration to the Attribute Table.
*
* @note It is currently only possible to add an include declaration to the last added service (i.e. only sequential population is supported at this time).
*
* @note The included service must already be present in the Attribute Table prior to this call.
*
* @mscs
* @mmsc{@ref BLE_GATTS_ATT_TABLE_POP_MSC}
* @endmscs
*
* @param[in] service_handle Handle of the service where the included service is to be placed, if @ref BLE_GATT_HANDLE_INVALID is used, it will be placed sequentially.
* @param[in] inc_srvc_handle Handle of the included service.
* @param[out] p_include_handle Pointer to a 16-bit word where the assigned handle will be stored.
*
* @retval ::NRF_SUCCESS Successfully added an include declaration.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, handle values need to match previously added services.
* @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation.
* @retval ::NRF_ERROR_NOT_SUPPORTED Feature is not supported, service_handle must be that of the last added service.
* @retval ::NRF_ERROR_FORBIDDEN Forbidden value supplied, self inclusions are not allowed.
* @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation.
* @retval ::NRF_ERROR_NOT_FOUND Attribute not found.
*/
SVCALL(SD_BLE_GATTS_INCLUDE_ADD, uint32_t, sd_ble_gatts_include_add(uint16_t service_handle, uint16_t inc_srvc_handle, uint16_t *p_include_handle));
/**@brief Add a characteristic declaration, a characteristic value declaration and optional characteristic descriptor declarations to the Attribute Table.
*
* @note It is currently only possible to add a characteristic to the last added service (i.e. only sequential population is supported at this time).
*
* @note Several restrictions apply to the parameters, such as matching permissions between the user description descriptor and the writable auxiliaries bits,
* readable (no security) and writable (selectable) CCCDs and SCCDs and valid presentation format values.
*
* @note If no metadata is provided for the optional descriptors, their permissions will be derived from the characteristic permissions.
*
* @mscs
* @mmsc{@ref BLE_GATTS_ATT_TABLE_POP_MSC}
* @endmscs
*
* @param[in] service_handle Handle of the service where the characteristic is to be placed, if @ref BLE_GATT_HANDLE_INVALID is used, it will be placed sequentially.
* @param[in] p_char_md Characteristic metadata.
* @param[in] p_attr_char_value Pointer to the attribute structure corresponding to the characteristic value.
* @param[out] p_handles Pointer to the structure where the assigned handles will be stored.
*
* @retval ::NRF_SUCCESS Successfully added a characteristic.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, service handle, Vendor Specific UUIDs, lengths, and permissions need to adhere to the constraints.
* @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation, a service context is required.
* @retval ::NRF_ERROR_FORBIDDEN Forbidden value supplied, certain UUIDs are reserved for the stack.
* @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation.
* @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied, attribute lengths are restricted by @ref BLE_GATTS_ATTR_LENS_MAX.
*/
SVCALL(SD_BLE_GATTS_CHARACTERISTIC_ADD, uint32_t, sd_ble_gatts_characteristic_add(uint16_t service_handle, ble_gatts_char_md_t const *p_char_md, ble_gatts_attr_t const *p_attr_char_value, ble_gatts_char_handles_t *p_handles));
/**@brief Add a descriptor to the Attribute Table.
*
* @note It is currently only possible to add a descriptor to the last added characteristic (i.e. only sequential population is supported at this time).
*
* @mscs
* @mmsc{@ref BLE_GATTS_ATT_TABLE_POP_MSC}
* @endmscs
*
* @param[in] char_handle Handle of the characteristic where the descriptor is to be placed, if @ref BLE_GATT_HANDLE_INVALID is used, it will be placed sequentially.
* @param[in] p_attr Pointer to the attribute structure.
* @param[out] p_handle Pointer to a 16-bit word where the assigned handle will be stored.
*
* @retval ::NRF_SUCCESS Successfully added a descriptor.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, characteristic handle, Vendor Specific UUIDs, lengths, and permissions need to adhere to the constraints.
* @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation, a characteristic context is required.
* @retval ::NRF_ERROR_FORBIDDEN Forbidden value supplied, certain UUIDs are reserved for the stack.
* @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation.
* @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied, attribute lengths are restricted by @ref BLE_GATTS_ATTR_LENS_MAX.
*/
SVCALL(SD_BLE_GATTS_DESCRIPTOR_ADD, uint32_t, sd_ble_gatts_descriptor_add(uint16_t char_handle, ble_gatts_attr_t const *p_attr, uint16_t *p_handle));
/**@brief Set the value of a given attribute.
*
* @note Values other than system attributes can be set at any time, regardless of whether any active connections exist.
*
* @mscs
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_QUEUE_FULL_MSC}
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_NOBUF_NOAUTH_MSC}
* @endmscs
*
* @param[in] conn_handle Connection handle. Ignored if the value does not belong to a system attribute.
* @param[in] handle Attribute handle.
* @param[in,out] p_value Attribute value information.
*
* @retval ::NRF_SUCCESS Successfully set the value of the attribute.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
* @retval ::NRF_ERROR_NOT_FOUND Attribute not found.
* @retval ::NRF_ERROR_FORBIDDEN Forbidden handle supplied, certain attributes are not modifiable by the application.
* @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied, attribute lengths are restricted by @ref BLE_GATTS_ATTR_LENS_MAX.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied on a system attribute.
*/
SVCALL(SD_BLE_GATTS_VALUE_SET, uint32_t, sd_ble_gatts_value_set(uint16_t conn_handle, uint16_t handle, ble_gatts_value_t *p_value));
/**@brief Get the value of a given attribute.
*
* @note If the attribute value is longer than the size of the supplied buffer,
* @ref ble_gatts_value_t::len will return the total attribute value length (excluding offset),
* and not the number of bytes actually returned in @ref ble_gatts_value_t::p_value.
* The application may use this information to allocate a suitable buffer size.
*
* @note When retrieving system attribute values with this function, the connection handle
* may refer to an already disconnected connection. Refer to the documentation of
* @ref sd_ble_gatts_sys_attr_get for further information.
*
* @param[in] conn_handle Connection handle. Ignored if the value does not belong to a system attribute.
* @param[in] handle Attribute handle.
* @param[in,out] p_value Attribute value information.
*
* @retval ::NRF_SUCCESS Successfully retrieved the value of the attribute.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_NOT_FOUND Attribute not found.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid attribute offset supplied.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied on a system attribute.
* @retval ::BLE_ERROR_GATTS_SYS_ATTR_MISSING System attributes missing, use @ref sd_ble_gatts_sys_attr_set to set them to a known value.
*/
SVCALL(SD_BLE_GATTS_VALUE_GET, uint32_t, sd_ble_gatts_value_get(uint16_t conn_handle, uint16_t handle, ble_gatts_value_t *p_value));
/**@brief Notify or Indicate an attribute value.
*
* @details This function checks for the relevant Client Characteristic Configuration descriptor value to verify that the relevant operation
* (notification or indication) has been enabled by the client. It is also able to update the attribute value before issuing the PDU, so that
* the application can atomically perform a value update and a server initiated transaction with a single API call.
*
* @note The local attribute value may be updated even if an outgoing packet is not sent to the peer due to an error during execution.
* The Attribute Table has been updated if one of the following error codes is returned: @ref NRF_ERROR_INVALID_STATE, @ref NRF_ERROR_BUSY,
* @ref NRF_ERROR_FORBIDDEN, @ref BLE_ERROR_GATTS_SYS_ATTR_MISSING and @ref NRF_ERROR_RESOURCES.
* The caller can check whether the value has been updated by looking at the contents of *(@ref ble_gatts_hvx_params_t::p_len).
*
* @note Only one indication procedure can be ongoing per connection at a time.
* If the application tries to indicate an attribute value while another indication procedure is ongoing,
* the function call will return @ref NRF_ERROR_BUSY.
* A @ref BLE_GATTS_EVT_HVC event will be issued as soon as the confirmation arrives from the peer.
*
* @note The number of Handle Value Notifications that can be queued is configured by @ref ble_gatts_conn_cfg_t::hvn_tx_queue_size
* When the queue is full, the function call will return @ref NRF_ERROR_RESOURCES.
* A @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event will be issued as soon as the transmission of the notification is complete.
*
* @note The application can keep track of the available queue element count for notifications by following the procedure below:
* - Store initial queue element count in a variable.
* - Decrement the variable, which stores the currently available queue element count, by one when a call to this function returns @ref NRF_SUCCESS.
* - Increment the variable, which stores the current available queue element count, by the count variable in @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event.
*
* @events
* @event{@ref BLE_GATTS_EVT_HVN_TX_COMPLETE, Notification transmission complete.}
* @event{@ref BLE_GATTS_EVT_HVC, Confirmation received from the peer.}
* @endevents
*
* @mscs
* @mmsc{@ref BLE_GATTS_HVX_SYS_ATTRS_MISSING_MSC}
* @mmsc{@ref BLE_GATTS_HVN_MSC}
* @mmsc{@ref BLE_GATTS_HVI_MSC}
* @mmsc{@ref BLE_GATTS_HVX_DISABLED_MSC}
* @endmscs
*
* @param[in] conn_handle Connection handle.
* @param[in,out] p_hvx_params Pointer to an HVx parameters structure. If @ref ble_gatts_hvx_params_t::p_data
* contains a non-NULL pointer the attribute value will be updated with the contents
* pointed by it before sending the notification or indication. If the attribute value
* is updated, @ref ble_gatts_hvx_params_t::p_len is updated by the SoftDevice to
* contain the number of actual bytes written, else it will be set to 0.
*
* @retval ::NRF_SUCCESS Successfully queued a notification or indication for transmission, and optionally updated the attribute value.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_STATE One or more of the following is true:
* - Invalid Connection State
* - Notifications and/or indications not enabled in the CCCD
* - An ATT_MTU exchange is ongoing
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
* @retval ::BLE_ERROR_INVALID_ATTR_HANDLE Invalid attribute handle(s) supplied. Only attributes added directly by the application are available to notify and indicate.
* @retval ::BLE_ERROR_GATTS_INVALID_ATTR_TYPE Invalid attribute type(s) supplied, only characteristic values may be notified and indicated.
* @retval ::NRF_ERROR_NOT_FOUND Attribute not found.
* @retval ::NRF_ERROR_FORBIDDEN The connection's current security level is lower than the one required by the write permissions of the CCCD associated with this characteristic.
* @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied.
* @retval ::NRF_ERROR_BUSY For @ref BLE_GATT_HVX_INDICATION Procedure already in progress. Wait for a @ref BLE_GATTS_EVT_HVC event and retry.
* @retval ::BLE_ERROR_GATTS_SYS_ATTR_MISSING System attributes missing, use @ref sd_ble_gatts_sys_attr_set to set them to a known value.
* @retval ::NRF_ERROR_RESOURCES Too many notifications queued.
* Wait for a @ref BLE_GATTS_EVT_HVN_TX_COMPLETE event and retry.
* @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection.
*/
SVCALL(SD_BLE_GATTS_HVX, uint32_t, sd_ble_gatts_hvx(uint16_t conn_handle, ble_gatts_hvx_params_t const *p_hvx_params));
/**@brief Indicate the Service Changed attribute value.
*
* @details This call will send a Handle Value Indication to one or more peers connected to inform them that the Attribute
* Table layout has changed. As soon as the peer has confirmed the indication, a @ref BLE_GATTS_EVT_SC_CONFIRM event will
* be issued.
*
* @note Some of the restrictions and limitations that apply to @ref sd_ble_gatts_hvx also apply here.
*
* @events
* @event{@ref BLE_GATTS_EVT_SC_CONFIRM, Confirmation of attribute table change received from peer.}
* @endevents
*
* @mscs
* @mmsc{@ref BLE_GATTS_SC_MSC}
* @endmscs
*
* @param[in] conn_handle Connection handle.
* @param[in] start_handle Start of affected attribute handle range.
* @param[in] end_handle End of affected attribute handle range.
*
* @retval ::NRF_SUCCESS Successfully queued the Service Changed indication for transmission.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_NOT_SUPPORTED Service Changed not enabled at initialization. See @ref
* sd_ble_cfg_set and @ref ble_gatts_cfg_service_changed_t.
* @retval ::NRF_ERROR_INVALID_STATE One or more of the following is true:
* - Invalid Connection State
* - Notifications and/or indications not enabled in the CCCD
* - An ATT_MTU exchange is ongoing
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
* @retval ::BLE_ERROR_INVALID_ATTR_HANDLE Invalid attribute handle(s) supplied, handles must be in the range populated by the application.
* @retval ::NRF_ERROR_BUSY Procedure already in progress.
* @retval ::BLE_ERROR_GATTS_SYS_ATTR_MISSING System attributes missing, use @ref sd_ble_gatts_sys_attr_set to set them to a known value.
* @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection.
*/
SVCALL(SD_BLE_GATTS_SERVICE_CHANGED, uint32_t, sd_ble_gatts_service_changed(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle));
/**@brief Respond to a Read/Write authorization request.
*
* @note This call should only be used as a response to a @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event issued to the application.
*
* @mscs
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_NOBUF_AUTH_MSC}
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_BUF_AUTH_MSC}
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_NOBUF_NOAUTH_MSC}
* @mmsc{@ref BLE_GATTS_READ_REQ_AUTH_MSC}
* @mmsc{@ref BLE_GATTS_WRITE_REQ_AUTH_MSC}
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_QUEUE_FULL_MSC}
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_PEER_CANCEL_MSC}
* @endmscs
*
* @param[in] conn_handle Connection handle.
* @param[in] p_rw_authorize_reply_params Pointer to a structure with the attribute provided by the application.
*
* @note @ref ble_gatts_authorize_params_t::p_data is ignored when this function is used to respond
* to a @ref BLE_GATTS_AUTHORIZE_TYPE_READ event if @ref ble_gatts_authorize_params_t::update
* is set to 0.
*
* @retval ::NRF_SUCCESS Successfully queued a response to the peer, and in the case of a write operation, Attribute Table updated.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State or no authorization request pending.
* @retval ::NRF_ERROR_INVALID_PARAM Authorization op invalid,
* handle supplied does not match requested handle,
* or invalid data to be written provided by the application.
* @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection.
*/
SVCALL(SD_BLE_GATTS_RW_AUTHORIZE_REPLY, uint32_t, sd_ble_gatts_rw_authorize_reply(uint16_t conn_handle, ble_gatts_rw_authorize_reply_params_t const *p_rw_authorize_reply_params));
/**@brief Update persistent system attribute information.
*
* @details Supply information about persistent system attributes to the stack,
* previously obtained using @ref sd_ble_gatts_sys_attr_get.
* This call is only allowed for active connections, and is usually
* made immediately after a connection is established with an known bonded device,
* often as a response to a @ref BLE_GATTS_EVT_SYS_ATTR_MISSING.
*
* p_sysattrs may point directly to the application's stored copy of the system attributes
* obtained using @ref sd_ble_gatts_sys_attr_get.
* If the pointer is NULL, the system attribute info is initialized, assuming that
* the application does not have any previously saved system attribute data for this device.
*
* @note The state of persistent system attributes is reset upon connection establishment and then remembered for its duration.
*
* @note If this call returns with an error code different from @ref NRF_SUCCESS, the storage of persistent system attributes may have been completed only partially.
* This means that the state of the attribute table is undefined, and the application should either provide a new set of attributes using this same call or
* reset the SoftDevice to return to a known state.
*
* @note When the @ref BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS is used with this function, only the system attributes included in system services will be modified.
* @note When the @ref BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS is used with this function, only the system attributes included in user services will be modified.
*
* @mscs
* @mmsc{@ref BLE_GATTS_HVX_SYS_ATTRS_MISSING_MSC}
* @mmsc{@ref BLE_GATTS_SYS_ATTRS_UNK_PEER_MSC}
* @mmsc{@ref BLE_GATTS_SYS_ATTRS_BONDED_PEER_MSC}
* @endmscs
*
* @param[in] conn_handle Connection handle.
* @param[in] p_sys_attr_data Pointer to a saved copy of system attributes supplied to the stack, or NULL.
* @param[in] len Size of data pointed by p_sys_attr_data, in octets.
* @param[in] flags Optional additional flags, see @ref BLE_GATTS_SYS_ATTR_FLAGS
*
* @retval ::NRF_SUCCESS Successfully set the system attribute information.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid flags supplied.
* @retval ::NRF_ERROR_INVALID_DATA Invalid data supplied, the data should be exactly the same as retrieved with @ref sd_ble_gatts_sys_attr_get.
* @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation.
*/
SVCALL(SD_BLE_GATTS_SYS_ATTR_SET, uint32_t, sd_ble_gatts_sys_attr_set(uint16_t conn_handle, uint8_t const *p_sys_attr_data, uint16_t len, uint32_t flags));
/**@brief Retrieve persistent system attribute information from the stack.
*
* @details This call is used to retrieve information about values to be stored persistently by the application
* during the lifetime of a connection or after it has been terminated. When a new connection is established with the same bonded device,
* the system attribute information retrieved with this function should be restored using using @ref sd_ble_gatts_sys_attr_set.
* If retrieved after disconnection, the data should be read before a new connection established. The connection handle for
* the previous, now disconnected, connection will remain valid until a new one is created to allow this API call to refer to it.
* Connection handles belonging to active connections can be used as well, but care should be taken since the system attributes
* may be written to at any time by the peer during a connection's lifetime.
*
* @note When the @ref BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS is used with this function, only the system attributes included in system services will be returned.
* @note When the @ref BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS is used with this function, only the system attributes included in user services will be returned.
*
* @mscs
* @mmsc{@ref BLE_GATTS_SYS_ATTRS_BONDED_PEER_MSC}
* @endmscs
*
* @param[in] conn_handle Connection handle of the recently terminated connection.
* @param[out] p_sys_attr_data Pointer to a buffer where updated information about system attributes will be filled in. The format of the data is described
* in @ref BLE_GATTS_SYS_ATTRS_FORMAT. NULL can be provided to obtain the length of the data.
* @param[in,out] p_len Size of application buffer if p_sys_attr_data is not NULL. Unconditionally updated to actual length of system attribute data.
* @param[in] flags Optional additional flags, see @ref BLE_GATTS_SYS_ATTR_FLAGS
*
* @retval ::NRF_SUCCESS Successfully retrieved the system attribute information.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid flags supplied.
* @retval ::NRF_ERROR_DATA_SIZE The system attribute information did not fit into the provided buffer.
* @retval ::NRF_ERROR_NOT_FOUND No system attributes found.
*/
SVCALL(SD_BLE_GATTS_SYS_ATTR_GET, uint32_t, sd_ble_gatts_sys_attr_get(uint16_t conn_handle, uint8_t *p_sys_attr_data, uint16_t *p_len, uint32_t flags));
/**@brief Retrieve the first valid user attribute handle.
*
* @param[out] p_handle Pointer to an integer where the handle will be stored.
*
* @retval ::NRF_SUCCESS Successfully retrieved the handle.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
*/
SVCALL(SD_BLE_GATTS_INITIAL_USER_HANDLE_GET, uint32_t, sd_ble_gatts_initial_user_handle_get(uint16_t *p_handle));
/**@brief Retrieve the attribute UUID and/or metadata.
*
* @param[in] handle Attribute handle
* @param[out] p_uuid UUID of the attribute. Use NULL to omit this field.
* @param[out] p_md Metadata of the attribute. Use NULL to omit this field.
*
* @retval ::NRF_SUCCESS Successfully retrieved the attribute metadata,
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameters supplied. Returned when both @c p_uuid and @c p_md are NULL.
* @retval ::NRF_ERROR_NOT_FOUND Attribute was not found.
*/
SVCALL(SD_BLE_GATTS_ATTR_GET, uint32_t, sd_ble_gatts_attr_get(uint16_t handle, ble_uuid_t * p_uuid, ble_gatts_attr_md_t * p_md));
/**@brief Reply to an ATT_MTU exchange request by sending an Exchange MTU Response to the client.
*
* @details This function is only used to reply to a @ref BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST event.
*
* @details The SoftDevice sets ATT_MTU to the minimum of:
* - The Client RX MTU value from @ref BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST, and
* - The Server RX MTU value.
*
* However, the SoftDevice never sets ATT_MTU lower than @ref BLE_GATT_ATT_MTU_DEFAULT.
*
* @mscs
* @mmsc{@ref BLE_GATTS_MTU_EXCHANGE}
* @endmscs
*
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
* @param[in] server_rx_mtu Server RX MTU size.
* - The minimum value is @ref BLE_GATT_ATT_MTU_DEFAULT.
* - The maximum value is @ref ble_gatt_conn_cfg_t::att_mtu in the connection configuration
* used for this connection.
* - The value must be equal to Client RX MTU size given in @ref sd_ble_gattc_exchange_mtu_request
* if an ATT_MTU exchange has already been performed in the other direction.
*
* @retval ::NRF_SUCCESS Successfully sent response to the client.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State or no ATT_MTU exchange request pending.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid Server RX MTU size supplied.
* @retval ::NRF_ERROR_TIMEOUT There has been a GATT procedure timeout. No new GATT procedure can be performed without reestablishing the connection.
*/
SVCALL(SD_BLE_GATTS_EXCHANGE_MTU_REPLY, uint32_t, sd_ble_gatts_exchange_mtu_reply(uint16_t conn_handle, uint16_t server_rx_mtu));
/** @} */
#ifdef __cplusplus
}
#endif
#endif // BLE_GATTS_H__
/**
@}
*/

View File

@ -0,0 +1,135 @@
/*
* 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.
*/
/**
@addtogroup BLE_COMMON
@{
*/
#ifndef BLE_HCI_H__
#define BLE_HCI_H__
#ifdef __cplusplus
extern "C" {
#endif
/** @defgroup BLE_HCI_STATUS_CODES Bluetooth status codes
* @{ */
#define BLE_HCI_STATUS_CODE_SUCCESS 0x00 /**< Success. */
#define BLE_HCI_STATUS_CODE_UNKNOWN_BTLE_COMMAND 0x01 /**< Unknown BLE Command. */
#define BLE_HCI_STATUS_CODE_UNKNOWN_CONNECTION_IDENTIFIER 0x02 /**< Unknown Connection Identifier. */
/*0x03 Hardware Failure
0x04 Page Timeout
*/
#define BLE_HCI_AUTHENTICATION_FAILURE 0x05 /**< Authentication Failure. */
#define BLE_HCI_STATUS_CODE_PIN_OR_KEY_MISSING 0x06 /**< Pin or Key missing. */
#define BLE_HCI_MEMORY_CAPACITY_EXCEEDED 0x07 /**< Memory Capacity Exceeded. */
#define BLE_HCI_CONNECTION_TIMEOUT 0x08 /**< Connection Timeout. */
/*0x09 Connection Limit Exceeded
0x0A Synchronous Connection Limit To A Device Exceeded
0x0B ACL Connection Already Exists*/
#define BLE_HCI_STATUS_CODE_COMMAND_DISALLOWED 0x0C /**< Command Disallowed. */
/*0x0D Connection Rejected due to Limited Resources
0x0E Connection Rejected Due To Security Reasons
0x0F Connection Rejected due to Unacceptable BD_ADDR
0x10 Connection Accept Timeout Exceeded
0x11 Unsupported Feature or Parameter Value*/
#define BLE_HCI_STATUS_CODE_INVALID_BTLE_COMMAND_PARAMETERS 0x12 /**< Invalid BLE Command Parameters. */
#define BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION 0x13 /**< Remote User Terminated Connection. */
#define BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES 0x14 /**< Remote Device Terminated Connection due to low resources.*/
#define BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF 0x15 /**< Remote Device Terminated Connection due to power off. */
#define BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION 0x16 /**< Local Host Terminated Connection. */
/*
0x17 Repeated Attempts
0x18 Pairing Not Allowed
0x19 Unknown LMP PDU
*/
#define BLE_HCI_UNSUPPORTED_REMOTE_FEATURE 0x1A /**< Unsupported Remote Feature. */
/*
0x1B SCO Offset Rejected
0x1C SCO Interval Rejected
0x1D SCO Air Mode Rejected*/
#define BLE_HCI_STATUS_CODE_INVALID_LMP_PARAMETERS 0x1E /**< Invalid LMP Parameters. */
#define BLE_HCI_STATUS_CODE_UNSPECIFIED_ERROR 0x1F /**< Unspecified Error. */
/*0x20 Unsupported LMP Parameter Value
0x21 Role Change Not Allowed
*/
#define BLE_HCI_STATUS_CODE_LMP_RESPONSE_TIMEOUT 0x22 /**< LMP Response Timeout. */
#define BLE_HCI_STATUS_CODE_LMP_ERROR_TRANSACTION_COLLISION 0x23 /**< LMP Error Transaction Collision/LL Procedure Collision. */
#define BLE_HCI_STATUS_CODE_LMP_PDU_NOT_ALLOWED 0x24 /**< LMP PDU Not Allowed. */
/*0x25 Encryption Mode Not Acceptable
0x26 Link Key Can Not be Changed
0x27 Requested QoS Not Supported
*/
#define BLE_HCI_INSTANT_PASSED 0x28 /**< Instant Passed. */
#define BLE_HCI_PAIRING_WITH_UNIT_KEY_UNSUPPORTED 0x29 /**< Pairing with Unit Key Unsupported. */
#define BLE_HCI_DIFFERENT_TRANSACTION_COLLISION 0x2A /**< Different Transaction Collision. */
/*
0x2B Reserved
0x2C QoS Unacceptable Parameter
0x2D QoS Rejected
0x2E Channel Classification Not Supported
0x2F Insufficient Security
*/
#define BLE_HCI_PARAMETER_OUT_OF_MANDATORY_RANGE 0x30 /**< Parameter Out Of Mandatory Range. */
/*
0x31 Reserved
0x32 Role Switch Pending
0x33 Reserved
0x34 Reserved Slot Violation
0x35 Role Switch Failed
0x36 Extended Inquiry Response Too Large
0x37 Secure Simple Pairing Not Supported By Host.
0x38 Host Busy - Pairing
0x39 Connection Rejected due to No Suitable Channel Found*/
#define BLE_HCI_CONTROLLER_BUSY 0x3A /**< Controller Busy. */
#define BLE_HCI_CONN_INTERVAL_UNACCEPTABLE 0x3B /**< Connection Interval Unacceptable. */
#define BLE_HCI_DIRECTED_ADVERTISER_TIMEOUT 0x3C /**< Directed Advertisement Timeout. */
#define BLE_HCI_CONN_TERMINATED_DUE_TO_MIC_FAILURE 0x3D /**< Connection Terminated due to MIC Failure. */
#define BLE_HCI_CONN_FAILED_TO_BE_ESTABLISHED 0x3E /**< Connection Failed to be Established. */
/** @} */
#ifdef __cplusplus
}
#endif
#endif // BLE_HCI_H__
/** @} */

View File

@ -0,0 +1,506 @@
/*
* Copyright (c) 2011 - 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.
*/
/**
@addtogroup BLE_L2CAP Logical Link Control and Adaptation Protocol (L2CAP)
@{
@brief Definitions and prototypes for the L2CAP interface.
*/
#ifndef BLE_L2CAP_H__
#define BLE_L2CAP_H__
#include <stdint.h>
#include "nrf_svc.h"
#include "nrf_error.h"
#include "ble_ranges.h"
#include "ble_types.h"
#include "ble_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@addtogroup BLE_L2CAP_TERMINOLOGY Terminology
* @{
* @details
*
* L2CAP SDU
* - A data unit that the application can send/receive to/from a peer.
*
* L2CAP PDU
* - A data unit that is exchanged between local and remote L2CAP entities.
* It consists of L2CAP protocol control information and payload fields.
* The payload field can contain an L2CAP SDU or a part of an L2CAP SDU.
*
* L2CAP MTU
* - The maximum length of an L2CAP SDU.
*
* L2CAP MPS
* - The maximum length of an L2CAP PDU payload field.
*
* Credits
* - A value indicating the number of L2CAP PDUs that the receiver of the credit can send to the peer.
* @} */
/**@addtogroup BLE_L2CAP_ENUMERATIONS Enumerations
* @{ */
/**@brief L2CAP API SVC numbers. */
enum BLE_L2CAP_SVCS
{
SD_BLE_L2CAP_CH_SETUP = BLE_L2CAP_SVC_BASE + 0, /**< Set up an L2CAP channel. */
SD_BLE_L2CAP_CH_RELEASE = BLE_L2CAP_SVC_BASE + 1, /**< Release an L2CAP channel. */
SD_BLE_L2CAP_CH_RX = BLE_L2CAP_SVC_BASE + 2, /**< Receive an SDU on an L2CAP channel. */
SD_BLE_L2CAP_CH_TX = BLE_L2CAP_SVC_BASE + 3, /**< Transmit an SDU on an L2CAP channel. */
SD_BLE_L2CAP_CH_FLOW_CONTROL = BLE_L2CAP_SVC_BASE + 4, /**< Advanced SDU reception flow control. */
};
/**@brief L2CAP Event IDs. */
enum BLE_L2CAP_EVTS
{
BLE_L2CAP_EVT_CH_SETUP_REQUEST = BLE_L2CAP_EVT_BASE + 0, /**< L2CAP Channel Setup Request event.
\n See @ref ble_l2cap_evt_ch_setup_request_t. */
BLE_L2CAP_EVT_CH_SETUP_REFUSED = BLE_L2CAP_EVT_BASE + 1, /**< L2CAP Channel Setup Refused event.
\n See @ref ble_l2cap_evt_ch_setup_refused_t. */
BLE_L2CAP_EVT_CH_SETUP = BLE_L2CAP_EVT_BASE + 2, /**< L2CAP Channel Setup Completed event.
\n See @ref ble_l2cap_evt_ch_setup_t. */
BLE_L2CAP_EVT_CH_RELEASED = BLE_L2CAP_EVT_BASE + 3, /**< L2CAP Channel Released event.
\n No additional event structure applies. */
BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED = BLE_L2CAP_EVT_BASE + 4, /**< L2CAP Channel SDU data buffer released event.
\n See @ref ble_l2cap_evt_ch_sdu_buf_released_t. */
BLE_L2CAP_EVT_CH_CREDIT = BLE_L2CAP_EVT_BASE + 5, /**< L2CAP Channel Credit received.
\n See @ref ble_l2cap_evt_ch_credit_t. */
BLE_L2CAP_EVT_CH_RX = BLE_L2CAP_EVT_BASE + 6, /**< L2CAP Channel SDU received.
\n See @ref ble_l2cap_evt_ch_rx_t. */
BLE_L2CAP_EVT_CH_TX = BLE_L2CAP_EVT_BASE + 7, /**< L2CAP Channel SDU transmitted.
\n See @ref ble_l2cap_evt_ch_tx_t. */
};
/** @} */
/**@addtogroup BLE_L2CAP_DEFINES Defines
* @{ */
/**@brief Maximum number of L2CAP channels per connection. */
#define BLE_L2CAP_CH_COUNT_MAX (64)
/**@brief Minimum L2CAP MTU, in bytes. */
#define BLE_L2CAP_MTU_MIN (23)
/**@brief Minimum L2CAP MPS, in bytes. */
#define BLE_L2CAP_MPS_MIN (23)
/**@brief Invalid CID. */
#define BLE_L2CAP_CID_INVALID (0x0000)
/**@brief Default number of credits for @ref sd_ble_l2cap_ch_flow_control. */
#define BLE_L2CAP_CREDITS_DEFAULT (1)
/**@defgroup BLE_L2CAP_CH_SETUP_REFUSED_SRCS L2CAP channel setup refused sources
* @{ */
#define BLE_L2CAP_CH_SETUP_REFUSED_SRC_LOCAL (0x01) /**< Local. */
#define BLE_L2CAP_CH_SETUP_REFUSED_SRC_REMOTE (0x02) /**< Remote. */
/** @} */
/** @defgroup BLE_L2CAP_CH_STATUS_CODES L2CAP channel status codes
* @{ */
#define BLE_L2CAP_CH_STATUS_CODE_SUCCESS (0x0000) /**< Success. */
#define BLE_L2CAP_CH_STATUS_CODE_LE_PSM_NOT_SUPPORTED (0x0002) /**< LE_PSM not supported. */
#define BLE_L2CAP_CH_STATUS_CODE_NO_RESOURCES (0x0004) /**< No resources available. */
#define BLE_L2CAP_CH_STATUS_CODE_INSUFF_AUTHENTICATION (0x0005) /**< Insufficient authentication. */
#define BLE_L2CAP_CH_STATUS_CODE_INSUFF_AUTHORIZATION (0x0006) /**< Insufficient authorization. */
#define BLE_L2CAP_CH_STATUS_CODE_INSUFF_ENC_KEY_SIZE (0x0007) /**< Insufficient encryption key size. */
#define BLE_L2CAP_CH_STATUS_CODE_INSUFF_ENC (0x0008) /**< Insufficient encryption. */
#define BLE_L2CAP_CH_STATUS_CODE_INVALID_SCID (0x0009) /**< Invalid Source CID. */
#define BLE_L2CAP_CH_STATUS_CODE_SCID_ALLOCATED (0x000A) /**< Source CID already allocated. */
#define BLE_L2CAP_CH_STATUS_CODE_UNACCEPTABLE_PARAMS (0x000B) /**< Unacceptable parameters. */
#define BLE_L2CAP_CH_STATUS_CODE_NOT_UNDERSTOOD (0x8000) /**< Command Reject received instead of LE Credit Based Connection Response. */
#define BLE_L2CAP_CH_STATUS_CODE_TIMEOUT (0xC000) /**< Operation timed out. */
/** @} */
/** @} */
/**@addtogroup BLE_L2CAP_STRUCTURES Structures
* @{ */
/**
* @brief BLE L2CAP connection configuration parameters, set with @ref sd_ble_cfg_set.
*
* @note These parameters are set per connection, so all L2CAP channels created on this connection
* will have the same parameters.
*
* @retval ::NRF_ERROR_INVALID_PARAM One or more of the following is true:
* - rx_mps is smaller than @ref BLE_L2CAP_MPS_MIN.
* - tx_mps is smaller than @ref BLE_L2CAP_MPS_MIN.
* - ch_count is greater than @ref BLE_L2CAP_CH_COUNT_MAX.
* @retval ::NRF_ERROR_NO_MEM rx_mps or tx_mps is set too high.
*/
typedef struct
{
uint16_t rx_mps; /**< The maximum L2CAP PDU payload size, in bytes, that L2CAP shall
be able to receive on L2CAP channels on connections with this
configuration. The minimum value is @ref BLE_L2CAP_MPS_MIN. */
uint16_t tx_mps; /**< The maximum L2CAP PDU payload size, in bytes, that L2CAP shall
be able to transmit on L2CAP channels on connections with this
configuration. The minimum value is @ref BLE_L2CAP_MPS_MIN. */
uint8_t rx_queue_size; /**< Number of SDU data buffers that can be queued for reception per
L2CAP channel. The minimum value is one. */
uint8_t tx_queue_size; /**< Number of SDU data buffers that can be queued for transmission
per L2CAP channel. The minimum value is one. */
uint8_t ch_count; /**< Number of L2CAP channels the application can create per connection
with this configuration. The default value is zero, the maximum
value is @ref BLE_L2CAP_CH_COUNT_MAX.
@note if this parameter is set to zero, all other parameters in
@ref ble_l2cap_conn_cfg_t are ignored. */
} ble_l2cap_conn_cfg_t;
/**@brief L2CAP channel RX parameters. */
typedef struct
{
uint16_t rx_mtu; /**< The maximum L2CAP SDU size, in bytes, that L2CAP shall be able to
receive on this L2CAP channel.
- Must be equal to or greater than @ref BLE_L2CAP_MTU_MIN. */
uint16_t rx_mps; /**< The maximum L2CAP PDU payload size, in bytes, that L2CAP shall be
able to receive on this L2CAP channel.
- Must be equal to or greater than @ref BLE_L2CAP_MPS_MIN.
- Must be equal to or less than @ref ble_l2cap_conn_cfg_t::rx_mps. */
ble_data_t sdu_buf; /**< SDU data buffer for reception.
- If @ref ble_data_t::p_data is non-NULL, initial credits are
issued to the peer.
- If @ref ble_data_t::p_data is NULL, no initial credits are
issued to the peer. */
} ble_l2cap_ch_rx_params_t;
/**@brief L2CAP channel setup parameters. */
typedef struct
{
ble_l2cap_ch_rx_params_t rx_params; /**< L2CAP channel RX parameters. */
uint16_t le_psm; /**< LE Protocol/Service Multiplexer. Used when requesting
setup of an L2CAP channel, ignored otherwise. */
uint16_t status; /**< Status code, see @ref BLE_L2CAP_CH_STATUS_CODES.
Used when replying to a setup request of an L2CAP
channel, ignored otherwise. */
} ble_l2cap_ch_setup_params_t;
/**@brief L2CAP channel TX parameters. */
typedef struct
{
uint16_t tx_mtu; /**< The maximum L2CAP SDU size, in bytes, that L2CAP is able to
transmit on this L2CAP channel. */
uint16_t peer_mps; /**< The maximum L2CAP PDU payload size, in bytes, that the peer is
able to receive on this L2CAP channel. */
uint16_t tx_mps; /**< The maximum L2CAP PDU payload size, in bytes, that L2CAP is able
to transmit on this L2CAP channel. This is effective tx_mps,
selected by the SoftDevice as
MIN( @ref ble_l2cap_ch_tx_params_t::peer_mps, @ref ble_l2cap_conn_cfg_t::tx_mps ) */
uint16_t credits; /**< Initial credits given by the peer. */
} ble_l2cap_ch_tx_params_t;
/**@brief L2CAP Channel Setup Request event. */
typedef struct
{
ble_l2cap_ch_tx_params_t tx_params; /**< L2CAP channel TX parameters. */
uint16_t le_psm; /**< LE Protocol/Service Multiplexer. */
} ble_l2cap_evt_ch_setup_request_t;
/**@brief L2CAP Channel Setup Refused event. */
typedef struct
{
uint8_t source; /**< Source, see @ref BLE_L2CAP_CH_SETUP_REFUSED_SRCS */
uint16_t status; /**< Status code, see @ref BLE_L2CAP_CH_STATUS_CODES */
} ble_l2cap_evt_ch_setup_refused_t;
/**@brief L2CAP Channel Setup Completed event. */
typedef struct
{
ble_l2cap_ch_tx_params_t tx_params; /**< L2CAP channel TX parameters. */
} ble_l2cap_evt_ch_setup_t;
/**@brief L2CAP Channel SDU Data Duffer Released event. */
typedef struct
{
ble_data_t sdu_buf; /**< Returned reception or transmission SDU data buffer. The SoftDevice
returns SDU data buffers supplied by the application, which have
not yet been returned previously via a @ref BLE_L2CAP_EVT_CH_RX or
@ref BLE_L2CAP_EVT_CH_TX event. */
} ble_l2cap_evt_ch_sdu_buf_released_t;
/**@brief L2CAP Channel Credit received event. */
typedef struct
{
uint16_t credits; /**< Additional credits given by the peer. */
} ble_l2cap_evt_ch_credit_t;
/**@brief L2CAP Channel received SDU event. */
typedef struct
{
uint16_t sdu_len; /**< Total SDU length, in bytes. */
ble_data_t sdu_buf; /**< SDU data buffer.
@note If there is not enough space in the buffer
(sdu_buf.len < sdu_len) then the rest of the SDU will be
silently discarded by the SoftDevice. */
} ble_l2cap_evt_ch_rx_t;
/**@brief L2CAP Channel transmitted SDU event. */
typedef struct
{
ble_data_t sdu_buf; /**< SDU data buffer. */
} ble_l2cap_evt_ch_tx_t;
/**@brief L2CAP event structure. */
typedef struct
{
uint16_t conn_handle; /**< Connection Handle on which the event occured. */
uint16_t local_cid; /**< Local Channel ID of the L2CAP channel, or
@ref BLE_L2CAP_CID_INVALID if not present. */
union
{
ble_l2cap_evt_ch_setup_request_t ch_setup_request; /**< L2CAP Channel Setup Request Event Parameters. */
ble_l2cap_evt_ch_setup_refused_t ch_setup_refused; /**< L2CAP Channel Setup Refused Event Parameters. */
ble_l2cap_evt_ch_setup_t ch_setup; /**< L2CAP Channel Setup Completed Event Parameters. */
ble_l2cap_evt_ch_sdu_buf_released_t ch_sdu_buf_released;/**< L2CAP Channel SDU Data Buffer Released Event Parameters. */
ble_l2cap_evt_ch_credit_t credit; /**< L2CAP Channel Credit Received Event Parameters. */
ble_l2cap_evt_ch_rx_t rx; /**< L2CAP Channel SDU Received Event Parameters. */
ble_l2cap_evt_ch_tx_t tx; /**< L2CAP Channel SDU Transmitted Event Parameters. */
} params; /**< Event Parameters. */
} ble_l2cap_evt_t;
/** @} */
/**@addtogroup BLE_L2CAP_FUNCTIONS Functions
* @{ */
/**@brief Set up an L2CAP channel.
*
* @details This function is used to:
* - Request setup of an L2CAP channel: sends an LE Credit Based Connection Request packet to a peer.
* - Reply to a setup request of an L2CAP channel (if called in response to a
* @ref BLE_L2CAP_EVT_CH_SETUP_REQUEST event): sends an LE Credit Based Connection
* Response packet to a peer.
*
* @note A call to this function will require the application to keep the SDU data buffer alive
* until the SDU data buffer is returned in @ref BLE_L2CAP_EVT_CH_RX or
* @ref BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED event.
*
* @events
* @event{@ref BLE_L2CAP_EVT_CH_SETUP, Setup successful.}
* @event{@ref BLE_L2CAP_EVT_CH_SETUP_REFUSED, Setup failed.}
* @endevents
*
* @mscs
* @mmsc{@ref BLE_L2CAP_CH_SETUP_MSC}
* @endmscs
*
* @param[in] conn_handle Connection Handle.
* @param[in,out] p_local_cid Pointer to a uint16_t containing Local Channel ID of the L2CAP channel:
* - As input: @ref BLE_L2CAP_CID_INVALID when requesting setup of an L2CAP
* channel or local_cid provided in the @ref BLE_L2CAP_EVT_CH_SETUP_REQUEST
* event when replying to a setup request of an L2CAP channel.
* - As output: local_cid for this channel.
* @param[in] p_params L2CAP channel parameters.
*
* @retval ::NRF_SUCCESS Successfully queued request or response for transmission.
* @retval ::NRF_ERROR_BUSY The stack is busy, process pending events and retry.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
* @retval ::NRF_ERROR_INVALID_LENGTH Supplied higher rx_mps than has been configured on this link.
* @retval ::NRF_ERROR_INVALID_STATE Invalid State to perform operation (L2CAP channel already set up).
* @retval ::NRF_ERROR_NOT_FOUND CID not found.
* @retval ::NRF_ERROR_RESOURCES The limit has been reached for available L2CAP channels,
* see @ref ble_l2cap_conn_cfg_t::ch_count.
*/
SVCALL(SD_BLE_L2CAP_CH_SETUP, uint32_t, sd_ble_l2cap_ch_setup(uint16_t conn_handle, uint16_t *p_local_cid, ble_l2cap_ch_setup_params_t const *p_params));
/**@brief Release an L2CAP channel.
*
* @details This sends a Disconnection Request packet to a peer.
*
* @events
* @event{@ref BLE_L2CAP_EVT_CH_RELEASED, Release complete.}
* @endevents
*
* @mscs
* @mmsc{@ref BLE_L2CAP_CH_RELEASE_MSC}
* @endmscs
*
* @param[in] conn_handle Connection Handle.
* @param[in] local_cid Local Channel ID of the L2CAP channel.
*
* @retval ::NRF_SUCCESS Successfully queued request for transmission.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_STATE Invalid State to perform operation (Setup or release is
* in progress for the L2CAP channel).
* @retval ::NRF_ERROR_NOT_FOUND CID not found.
*/
SVCALL(SD_BLE_L2CAP_CH_RELEASE, uint32_t, sd_ble_l2cap_ch_release(uint16_t conn_handle, uint16_t local_cid));
/**@brief Receive an SDU on an L2CAP channel.
*
* @details This may issue additional credits to the peer using an LE Flow Control Credit packet.
*
* @note A call to this function will require the application to keep the memory pointed by
* @ref ble_data_t::p_data alive until the SDU data buffer is returned in @ref BLE_L2CAP_EVT_CH_RX
* or @ref BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED event.
*
* @note The SoftDevice can queue up to @ref ble_l2cap_conn_cfg_t::rx_queue_size SDU data buffers
* for reception per L2CAP channel.
*
* @events
* @event{@ref BLE_L2CAP_EVT_CH_RX, The SDU is received.}
* @endevents
*
* @mscs
* @mmsc{@ref BLE_L2CAP_CH_RX_MSC}
* @endmscs
*
* @param[in] conn_handle Connection Handle.
* @param[in] local_cid Local Channel ID of the L2CAP channel.
* @param[in] p_sdu_buf Pointer to the SDU data buffer.
*
* @retval ::NRF_SUCCESS Buffer accepted.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_STATE Invalid State to perform operation (Setup or release is
* in progress for an L2CAP channel).
* @retval ::NRF_ERROR_NOT_FOUND CID not found.
* @retval ::NRF_ERROR_RESOURCES Too many SDU data buffers supplied. Wait for a
* @ref BLE_L2CAP_EVT_CH_RX event and retry.
*/
SVCALL(SD_BLE_L2CAP_CH_RX, uint32_t, sd_ble_l2cap_ch_rx(uint16_t conn_handle, uint16_t local_cid, ble_data_t const *p_sdu_buf));
/**@brief Transmit an SDU on an L2CAP channel.
*
* @note A call to this function will require the application to keep the memory pointed by
* @ref ble_data_t::p_data alive until the SDU data buffer is returned in @ref BLE_L2CAP_EVT_CH_TX
* or @ref BLE_L2CAP_EVT_CH_SDU_BUF_RELEASED event.
*
* @note The SoftDevice can queue up to @ref ble_l2cap_conn_cfg_t::tx_queue_size SDUs for
* transmission per L2CAP channel.
*
* @note The application can keep track of the available credits for transmission by following
* the procedure below:
* - Store initial credits given by the peer in a variable.
* (Initial credits are provided in a @ref BLE_L2CAP_EVT_CH_SETUP event.)
* - Decrement the variable, which stores the currently available credits, by
* ceiling((@ref ble_data_t::len + 2) / tx_mps) when a call to this function returns
* @ref NRF_SUCCESS. (tx_mps is provided in a @ref BLE_L2CAP_EVT_CH_SETUP event.)
* - Increment the variable, which stores the currently available credits, by additional
* credits given by the peer in a @ref BLE_L2CAP_EVT_CH_CREDIT event.
*
* @events
* @event{@ref BLE_L2CAP_EVT_CH_TX, The SDU is transmitted.}
* @endevents
*
* @mscs
* @mmsc{@ref BLE_L2CAP_CH_TX_MSC}
* @endmscs
*
* @param[in] conn_handle Connection Handle.
* @param[in] local_cid Local Channel ID of the L2CAP channel.
* @param[in] p_sdu_buf Pointer to the SDU data buffer.
*
* @retval ::NRF_SUCCESS Successfully queued L2CAP SDU for transmission.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_STATE Invalid State to perform operation (Setup or release is
* in progress for the L2CAP channel).
* @retval ::NRF_ERROR_NOT_FOUND CID not found.
* @retval ::NRF_ERROR_DATA_SIZE Invalid SDU length supplied, must not be more than
* @ref ble_l2cap_ch_tx_params_t::tx_mtu provided in
* @ref BLE_L2CAP_EVT_CH_SETUP event.
* @retval ::NRF_ERROR_RESOURCES Too many SDUs queued for transmission. Wait for a
* @ref BLE_L2CAP_EVT_CH_TX event and retry.
*/
SVCALL(SD_BLE_L2CAP_CH_TX, uint32_t, sd_ble_l2cap_ch_tx(uint16_t conn_handle, uint16_t local_cid, ble_data_t const *p_sdu_buf));
/**@brief Advanced SDU reception flow control.
*
* @details Adjust the way the SoftDevice issues credits to the peer.
* This may issue additional credits to the peer using an LE Flow Control Credit packet.
*
* @mscs
* @mmsc{@ref BLE_L2CAP_CH_FLOW_CONTROL_MSC}
* @endmscs
*
* @param[in] conn_handle Connection Handle.
* @param[in] local_cid Local Channel ID of the L2CAP channel or @ref BLE_L2CAP_CID_INVALID to set
* the value that will be used for newly created channels.
* @param[in] credits Number of credits that the SoftDevice will make sure the peer has every
* time it starts using a new reception buffer.
* - @ref BLE_L2CAP_CREDITS_DEFAULT is the default value the SoftDevice will
* use if this function is not called.
* - If set to zero, the SoftDevice will stop issuing credits for new reception
* buffers the application provides or has provided. SDU reception that is
* currently ongoing will be allowed to complete.
* @param[out] p_credits NULL or pointer to a uint16_t. If a valid pointer is provided, it will be
* written by the SoftDevice with the number of credits that is or will be
* available to the peer. If the value written by the SoftDevice is 0 when
* credits parameter was set to 0, the peer will not be able to send more
* data until more credits are provided by calling this function again with
* credits > 0. This parameter is ignored when local_cid is set to
* @ref BLE_L2CAP_CID_INVALID.
*
* @note Application should take care when setting number of credits higher than default value. In
* this case the application must make sure that the SoftDevice always has reception buffers
* available (see @ref sd_ble_l2cap_ch_rx) for that channel. If the SoftDevice does not have
* such buffers available, packets may be NACKed on the Link Layer and all Bluetooth traffic
* on the connection handle may be stalled until the SoftDevice again has an available
* reception buffer. This applies even if the application has used this call to set the
* credits back to default, or zero.
*
* @retval ::NRF_SUCCESS Flow control parameters accepted.
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
* @retval ::NRF_ERROR_INVALID_STATE Invalid State to perform operation (Setup or release is
* in progress for an L2CAP channel).
* @retval ::NRF_ERROR_NOT_FOUND CID not found.
*/
SVCALL(SD_BLE_L2CAP_CH_FLOW_CONTROL, uint32_t, sd_ble_l2cap_ch_flow_control(uint16_t conn_handle, uint16_t local_cid, uint16_t credits, uint16_t *p_credits));
/** @} */
#ifdef __cplusplus
}
#endif
#endif // BLE_L2CAP_H__
/**
@}
*/

View File

@ -0,0 +1,156 @@
/*
* 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.
*/
/**
@addtogroup BLE_COMMON
@{
@defgroup ble_ranges Module specific SVC, event and option number subranges
@{
@brief Definition of SVC, event and option number subranges for each API module.
@note
SVCs, event and option numbers are split into subranges for each API module.
Each module receives its entire allocated range of SVC calls, whether implemented or not,
but return BLE_ERROR_NOT_SUPPORTED for unimplemented or undefined calls in its range.
Note that the symbols BLE_<module>_SVC_LAST is the end of the allocated SVC range,
rather than the last SVC function call actually defined and implemented.
Specific SVC, event and option values are defined in each module's ble_<module>.h file,
which defines names of each individual SVC code based on the range start value.
*/
#ifndef BLE_RANGES_H__
#define BLE_RANGES_H__
#ifdef __cplusplus
extern "C" {
#endif
#define BLE_SVC_BASE 0x60 /**< Common BLE SVC base. */
#define BLE_SVC_LAST 0x6B /**< Common BLE SVC last. */
#define BLE_GAP_SVC_BASE 0x6C /**< GAP BLE SVC base. */
#define BLE_GAP_SVC_LAST 0x9A /**< GAP BLE SVC last. */
#define BLE_GATTC_SVC_BASE 0x9B /**< GATTC BLE SVC base. */
#define BLE_GATTC_SVC_LAST 0xA7 /**< GATTC BLE SVC last. */
#define BLE_GATTS_SVC_BASE 0xA8 /**< GATTS BLE SVC base. */
#define BLE_GATTS_SVC_LAST 0xB7 /**< GATTS BLE SVC last. */
#define BLE_L2CAP_SVC_BASE 0xB8 /**< L2CAP BLE SVC base. */
#define BLE_L2CAP_SVC_LAST 0xBF /**< L2CAP BLE SVC last. */
#define BLE_EVT_INVALID 0x00 /**< Invalid BLE Event. */
#define BLE_EVT_BASE 0x01 /**< Common BLE Event base. */
#define BLE_EVT_LAST 0x0F /**< Common BLE Event last. */
#define BLE_GAP_EVT_BASE 0x10 /**< GAP BLE Event base. */
#define BLE_GAP_EVT_LAST 0x2F /**< GAP BLE Event last. */
#define BLE_GATTC_EVT_BASE 0x30 /**< GATTC BLE Event base. */
#define BLE_GATTC_EVT_LAST 0x4F /**< GATTC BLE Event last. */
#define BLE_GATTS_EVT_BASE 0x50 /**< GATTS BLE Event base. */
#define BLE_GATTS_EVT_LAST 0x6F /**< GATTS BLE Event last. */
#define BLE_L2CAP_EVT_BASE 0x70 /**< L2CAP BLE Event base. */
#define BLE_L2CAP_EVT_LAST 0x8F /**< L2CAP BLE Event last. */
#define BLE_OPT_INVALID 0x00 /**< Invalid BLE Option. */
#define BLE_OPT_BASE 0x01 /**< Common BLE Option base. */
#define BLE_OPT_LAST 0x1F /**< Common BLE Option last. */
#define BLE_GAP_OPT_BASE 0x20 /**< GAP BLE Option base. */
#define BLE_GAP_OPT_LAST 0x3F /**< GAP BLE Option last. */
#define BLE_GATT_OPT_BASE 0x40 /**< GATT BLE Option base. */
#define BLE_GATT_OPT_LAST 0x5F /**< GATT BLE Option last. */
#define BLE_GATTC_OPT_BASE 0x60 /**< GATTC BLE Option base. */
#define BLE_GATTC_OPT_LAST 0x7F /**< GATTC BLE Option last. */
#define BLE_GATTS_OPT_BASE 0x80 /**< GATTS BLE Option base. */
#define BLE_GATTS_OPT_LAST 0x9F /**< GATTS BLE Option last. */
#define BLE_L2CAP_OPT_BASE 0xA0 /**< L2CAP BLE Option base. */
#define BLE_L2CAP_OPT_LAST 0xBF /**< L2CAP BLE Option last. */
#define BLE_CFG_INVALID 0x00 /**< Invalid BLE configuration. */
#define BLE_CFG_BASE 0x01 /**< Common BLE configuration base. */
#define BLE_CFG_LAST 0x1F /**< Common BLE configuration last. */
#define BLE_CONN_CFG_BASE 0x20 /**< BLE connection configuration base. */
#define BLE_CONN_CFG_LAST 0x3F /**< BLE connection configuration last. */
#define BLE_GAP_CFG_BASE 0x40 /**< GAP BLE configuration base. */
#define BLE_GAP_CFG_LAST 0x5F /**< GAP BLE configuration last. */
#define BLE_GATT_CFG_BASE 0x60 /**< GATT BLE configuration base. */
#define BLE_GATT_CFG_LAST 0x7F /**< GATT BLE configuration last. */
#define BLE_GATTC_CFG_BASE 0x80 /**< GATTC BLE configuration base. */
#define BLE_GATTC_CFG_LAST 0x9F /**< GATTC BLE configuration last. */
#define BLE_GATTS_CFG_BASE 0xA0 /**< GATTS BLE configuration base. */
#define BLE_GATTS_CFG_LAST 0xBF /**< GATTS BLE configuration last. */
#define BLE_L2CAP_CFG_BASE 0xC0 /**< L2CAP BLE configuration base. */
#define BLE_L2CAP_CFG_LAST 0xDF /**< L2CAP BLE configuration last. */
#ifdef __cplusplus
}
#endif
#endif /* BLE_RANGES_H__ */
/**
@}
@}
*/

View File

@ -0,0 +1,215 @@
/*
* 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.
*/
/**
@addtogroup BLE_COMMON
@{
@defgroup ble_types Common types and macro definitions
@{
@brief Common types and macro definitions for the BLE SoftDevice.
*/
#ifndef BLE_TYPES_H__
#define BLE_TYPES_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup BLE_TYPES_DEFINES Defines
* @{ */
/** @defgroup BLE_CONN_HANDLES BLE Connection Handles
* @{ */
#define BLE_CONN_HANDLE_INVALID 0xFFFF /**< Invalid Connection Handle. */
#define BLE_CONN_HANDLE_ALL 0xFFFE /**< Applies to all Connection Handles. */
/** @} */
/** @defgroup BLE_UUID_VALUES Assigned Values for BLE UUIDs
* @{ */
/* Generic UUIDs, applicable to all services */
#define BLE_UUID_UNKNOWN 0x0000 /**< Reserved UUID. */
#define BLE_UUID_SERVICE_PRIMARY 0x2800 /**< Primary Service. */
#define BLE_UUID_SERVICE_SECONDARY 0x2801 /**< Secondary Service. */
#define BLE_UUID_SERVICE_INCLUDE 0x2802 /**< Include. */
#define BLE_UUID_CHARACTERISTIC 0x2803 /**< Characteristic. */
#define BLE_UUID_DESCRIPTOR_CHAR_EXT_PROP 0x2900 /**< Characteristic Extended Properties Descriptor. */
#define BLE_UUID_DESCRIPTOR_CHAR_USER_DESC 0x2901 /**< Characteristic User Description Descriptor. */
#define BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG 0x2902 /**< Client Characteristic Configuration Descriptor. */
#define BLE_UUID_DESCRIPTOR_SERVER_CHAR_CONFIG 0x2903 /**< Server Characteristic Configuration Descriptor. */
#define BLE_UUID_DESCRIPTOR_CHAR_PRESENTATION_FORMAT 0x2904 /**< Characteristic Presentation Format Descriptor. */
#define BLE_UUID_DESCRIPTOR_CHAR_AGGREGATE_FORMAT 0x2905 /**< Characteristic Aggregate Format Descriptor. */
/* GATT specific UUIDs */
#define BLE_UUID_GATT 0x1801 /**< Generic Attribute Profile. */
#define BLE_UUID_GATT_CHARACTERISTIC_SERVICE_CHANGED 0x2A05 /**< Service Changed Characteristic. */
/* GAP specific UUIDs */
#define BLE_UUID_GAP 0x1800 /**< Generic Access Profile. */
#define BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME 0x2A00 /**< Device Name Characteristic. */
#define BLE_UUID_GAP_CHARACTERISTIC_APPEARANCE 0x2A01 /**< Appearance Characteristic. */
#define BLE_UUID_GAP_CHARACTERISTIC_RECONN_ADDR 0x2A03 /**< Reconnection Address Characteristic. */
#define BLE_UUID_GAP_CHARACTERISTIC_PPCP 0x2A04 /**< Peripheral Preferred Connection Parameters Characteristic. */
#define BLE_UUID_GAP_CHARACTERISTIC_CAR 0x2AA6 /**< Central Address Resolution Characteristic. */
#define BLE_UUID_GAP_CHARACTERISTIC_RPA_ONLY 0x2AC9 /**< Resolvable Private Address Only Characteristic. */
/** @} */
/** @defgroup BLE_UUID_TYPES Types of UUID
* @{ */
#define BLE_UUID_TYPE_UNKNOWN 0x00 /**< Invalid UUID type. */
#define BLE_UUID_TYPE_BLE 0x01 /**< Bluetooth SIG UUID (16-bit). */
#define BLE_UUID_TYPE_VENDOR_BEGIN 0x02 /**< Vendor UUID types start at this index (128-bit). */
/** @} */
/** @defgroup BLE_APPEARANCES Bluetooth Appearance values
* @note Retrieved from http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
* @{ */
#define BLE_APPEARANCE_UNKNOWN 0 /**< Unknown. */
#define BLE_APPEARANCE_GENERIC_PHONE 64 /**< Generic Phone. */
#define BLE_APPEARANCE_GENERIC_COMPUTER 128 /**< Generic Computer. */
#define BLE_APPEARANCE_GENERIC_WATCH 192 /**< Generic Watch. */
#define BLE_APPEARANCE_WATCH_SPORTS_WATCH 193 /**< Watch: Sports Watch. */
#define BLE_APPEARANCE_GENERIC_CLOCK 256 /**< Generic Clock. */
#define BLE_APPEARANCE_GENERIC_DISPLAY 320 /**< Generic Display. */
#define BLE_APPEARANCE_GENERIC_REMOTE_CONTROL 384 /**< Generic Remote Control. */
#define BLE_APPEARANCE_GENERIC_EYE_GLASSES 448 /**< Generic Eye-glasses. */
#define BLE_APPEARANCE_GENERIC_TAG 512 /**< Generic Tag. */
#define BLE_APPEARANCE_GENERIC_KEYRING 576 /**< Generic Keyring. */
#define BLE_APPEARANCE_GENERIC_MEDIA_PLAYER 640 /**< Generic Media Player. */
#define BLE_APPEARANCE_GENERIC_BARCODE_SCANNER 704 /**< Generic Barcode Scanner. */
#define BLE_APPEARANCE_GENERIC_THERMOMETER 768 /**< Generic Thermometer. */
#define BLE_APPEARANCE_THERMOMETER_EAR 769 /**< Thermometer: Ear. */
#define BLE_APPEARANCE_GENERIC_HEART_RATE_SENSOR 832 /**< Generic Heart rate Sensor. */
#define BLE_APPEARANCE_HEART_RATE_SENSOR_HEART_RATE_BELT 833 /**< Heart Rate Sensor: Heart Rate Belt. */
#define BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE 896 /**< Generic Blood Pressure. */
#define BLE_APPEARANCE_BLOOD_PRESSURE_ARM 897 /**< Blood Pressure: Arm. */
#define BLE_APPEARANCE_BLOOD_PRESSURE_WRIST 898 /**< Blood Pressure: Wrist. */
#define BLE_APPEARANCE_GENERIC_HID 960 /**< Human Interface Device (HID). */
#define BLE_APPEARANCE_HID_KEYBOARD 961 /**< Keyboard (HID Subtype). */
#define BLE_APPEARANCE_HID_MOUSE 962 /**< Mouse (HID Subtype). */
#define BLE_APPEARANCE_HID_JOYSTICK 963 /**< Joystick (HID Subtype). */
#define BLE_APPEARANCE_HID_GAMEPAD 964 /**< Gamepad (HID Subtype). */
#define BLE_APPEARANCE_HID_DIGITIZERSUBTYPE 965 /**< Digitizer Tablet (HID Subtype). */
#define BLE_APPEARANCE_HID_CARD_READER 966 /**< Card Reader (HID Subtype). */
#define BLE_APPEARANCE_HID_DIGITAL_PEN 967 /**< Digital Pen (HID Subtype). */
#define BLE_APPEARANCE_HID_BARCODE 968 /**< Barcode Scanner (HID Subtype). */
#define BLE_APPEARANCE_GENERIC_GLUCOSE_METER 1024 /**< Generic Glucose Meter. */
#define BLE_APPEARANCE_GENERIC_RUNNING_WALKING_SENSOR 1088 /**< Generic Running Walking Sensor. */
#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_IN_SHOE 1089 /**< Running Walking Sensor: In-Shoe. */
#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_SHOE 1090 /**< Running Walking Sensor: On-Shoe. */
#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_HIP 1091 /**< Running Walking Sensor: On-Hip. */
#define BLE_APPEARANCE_GENERIC_CYCLING 1152 /**< Generic Cycling. */
#define BLE_APPEARANCE_CYCLING_CYCLING_COMPUTER 1153 /**< Cycling: Cycling Computer. */
#define BLE_APPEARANCE_CYCLING_SPEED_SENSOR 1154 /**< Cycling: Speed Sensor. */
#define BLE_APPEARANCE_CYCLING_CADENCE_SENSOR 1155 /**< Cycling: Cadence Sensor. */
#define BLE_APPEARANCE_CYCLING_POWER_SENSOR 1156 /**< Cycling: Power Sensor. */
#define BLE_APPEARANCE_CYCLING_SPEED_CADENCE_SENSOR 1157 /**< Cycling: Speed and Cadence Sensor. */
#define BLE_APPEARANCE_GENERIC_PULSE_OXIMETER 3136 /**< Generic Pulse Oximeter. */
#define BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP 3137 /**< Fingertip (Pulse Oximeter subtype). */
#define BLE_APPEARANCE_PULSE_OXIMETER_WRIST_WORN 3138 /**< Wrist Worn(Pulse Oximeter subtype). */
#define BLE_APPEARANCE_GENERIC_WEIGHT_SCALE 3200 /**< Generic Weight Scale. */
#define BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS_ACT 5184 /**< Generic Outdoor Sports Activity. */
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_DISP 5185 /**< Location Display Device (Outdoor Sports Activity subtype). */
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_DISP 5186 /**< Location and Navigation Display Device (Outdoor Sports Activity subtype). */
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_POD 5187 /**< Location Pod (Outdoor Sports Activity subtype). */
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_POD 5188 /**< Location and Navigation Pod (Outdoor Sports Activity subtype). */
/** @} */
/** @brief Set .type and .uuid fields of ble_uuid_struct to specified UUID value. */
#define BLE_UUID_BLE_ASSIGN(instance, value) do {\
instance.type = BLE_UUID_TYPE_BLE; \
instance.uuid = value;} while(0)
/** @brief Copy type and uuid members from src to dst ble_uuid_t pointer. Both pointers must be valid/non-null. */
#define BLE_UUID_COPY_PTR(dst, src) do {\
(dst)->type = (src)->type; \
(dst)->uuid = (src)->uuid;} while(0)
/** @brief Copy type and uuid members from src to dst ble_uuid_t struct. */
#define BLE_UUID_COPY_INST(dst, src) do {\
(dst).type = (src).type; \
(dst).uuid = (src).uuid;} while(0)
/** @brief Compare for equality both type and uuid members of two (valid, non-null) ble_uuid_t pointers. */
#define BLE_UUID_EQ(p_uuid1, p_uuid2) \
(((p_uuid1)->type == (p_uuid2)->type) && ((p_uuid1)->uuid == (p_uuid2)->uuid))
/** @brief Compare for difference both type and uuid members of two (valid, non-null) ble_uuid_t pointers. */
#define BLE_UUID_NEQ(p_uuid1, p_uuid2) \
(((p_uuid1)->type != (p_uuid2)->type) || ((p_uuid1)->uuid != (p_uuid2)->uuid))
/** @} */
/** @addtogroup BLE_TYPES_STRUCTURES Structures
* @{ */
/** @brief 128 bit UUID values. */
typedef struct
{
uint8_t uuid128[16]; /**< Little-Endian UUID bytes. */
} ble_uuid128_t;
/** @brief Bluetooth Low Energy UUID type, encapsulates both 16-bit and 128-bit UUIDs. */
typedef struct
{
uint16_t uuid; /**< 16-bit UUID value or octets 12-13 of 128-bit UUID. */
uint8_t type; /**< UUID type, see @ref BLE_UUID_TYPES. If type is @ref BLE_UUID_TYPE_UNKNOWN, the value of uuid is undefined. */
} ble_uuid_t;
/**@brief Data structure. */
typedef struct
{
uint8_t *p_data; /**< Pointer to the data buffer provided to/from the application. */
uint16_t len; /**< Length of the data buffer, in bytes. */
} ble_data_t;
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* BLE_TYPES_H__ */
/**
@}
@}
*/

View File

@ -0,0 +1,242 @@
/*
* Copyright (c) 2014 - 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.
*/
/**
@defgroup nrf_mbr_api Master Boot Record API
@{
@brief APIs for updating SoftDevice and BootLoader
*/
#ifndef NRF_MBR_H__
#define NRF_MBR_H__
#include "nrf_svc.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup NRF_MBR_DEFINES Defines
* @{ */
/**@brief MBR SVC Base number. */
#define MBR_SVC_BASE (0x18)
/**@brief Page size in words. */
#define MBR_PAGE_SIZE_IN_WORDS (1024)
/** @brief The size that must be reserved for the MBR when a SoftDevice is written to flash.
This is the offset where the first byte of the SoftDevice hex file is written.*/
#define MBR_SIZE (0x1000)
/** @} */
/** @addtogroup NRF_MBR_ENUMS Enumerations
* @{ */
/**@brief nRF Master Boot Record API SVC numbers. */
enum NRF_MBR_SVCS
{
SD_MBR_COMMAND = MBR_SVC_BASE, /**< ::sd_mbr_command */
};
/**@brief Possible values for ::sd_mbr_command_t.command */
enum NRF_MBR_COMMANDS
{
SD_MBR_COMMAND_COPY_BL, /**< Copy a new BootLoader. @see ::sd_mbr_command_copy_bl_t*/
SD_MBR_COMMAND_COPY_SD, /**< Copy a new SoftDevice. @see ::sd_mbr_command_copy_sd_t*/
SD_MBR_COMMAND_INIT_SD, /**< Initialize forwarding interrupts to SD, and run reset function in SD. Does not require any parameters in ::sd_mbr_command_t params.*/
SD_MBR_COMMAND_COMPARE, /**< This command works like memcmp. @see ::sd_mbr_command_compare_t*/
SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET, /**< Change the address the MBR starts after a reset. @see ::sd_mbr_command_vector_table_base_set_t*/
SD_MBR_COMMAND_RESERVED,
SD_MBR_COMMAND_IRQ_FORWARD_ADDRESS_SET, /**< Start forwarding all interrupts to this address. @see ::sd_mbr_command_irq_forward_address_set_t*/
};
/** @} */
/** @addtogroup NRF_MBR_TYPES Types
* @{ */
/**@brief This command copies part of a new SoftDevice
*
* The destination area is erased before copying.
* If dst is in the middle of a flash page, that whole flash page will be erased.
* If (dst+len) is in the middle of a flash page, that whole flash page will be erased.
*
* The user of this function is responsible for setting the BPROT registers.
*
* @retval ::NRF_SUCCESS indicates that the contents of the memory blocks where copied correctly.
* @retval ::NRF_ERROR_INTERNAL indicates that the contents of the memory blocks where not verified correctly after copying.
*/
typedef struct
{
uint32_t *src; /**< Pointer to the source of data to be copied.*/
uint32_t *dst; /**< Pointer to the destination where the content is to be copied.*/
uint32_t len; /**< Number of 32 bit words to copy. Must be a multiple of @ref MBR_PAGE_SIZE_IN_WORDS words.*/
} sd_mbr_command_copy_sd_t;
/**@brief This command works like memcmp, but takes the length in words.
*
* @retval ::NRF_SUCCESS indicates that the contents of both memory blocks are equal.
* @retval ::NRF_ERROR_NULL indicates that the contents of the memory blocks are not equal.
*/
typedef struct
{
uint32_t *ptr1; /**< Pointer to block of memory. */
uint32_t *ptr2; /**< Pointer to block of memory. */
uint32_t len; /**< Number of 32 bit words to compare.*/
} sd_mbr_command_compare_t;
/**@brief This command copies a new BootLoader.
*
* With this command, destination of BootLoader is always the address written in
* NRF_UICR->BOOTADDR.
*
* Destination is erased by this function.
* If (destination+bl_len) is in the middle of a flash page, that whole flash page will be erased.
*
* This function will use the flash protect peripheral (BPROT or ACL) to protect the flash that is
* not intended to be written.
*
* On success, this function will not return. It will start the new BootLoader from reset-vector as normal.
*
* @retval ::NRF_ERROR_INTERNAL indicates an internal error that should not happen.
* @retval ::NRF_ERROR_FORBIDDEN if NRF_UICR->BOOTADDR is not set.
* @retval ::NRF_ERROR_INVALID_LENGTH if parameters attempts to read or write outside flash area.
* @retval ::NRF_ERROR_NO_MEM if no parameter page is provided (see SoftDevice Specification for more info)
*/
typedef struct
{
uint32_t *bl_src; /**< Pointer to the source of the Bootloader to be be copied.*/
uint32_t bl_len; /**< Number of 32 bit words to copy for BootLoader. */
} sd_mbr_command_copy_bl_t;
/**@brief Change the address the MBR starts after a reset
*
* Once this function has been called, this address is where the MBR will start to forward
* interrupts to after a reset.
*
* To restore default forwarding this function should be called with @ref address set to 0. The
* MBR will then start forwarding interrupts to the address in NFR_UICR->BOOTADDR or to the
* SoftDevice if the BOOTADDR is not set.
*
* On success, this function will not return. It will reset the device.
*
* @retval ::NRF_ERROR_INTERNAL indicates an internal error that should not happen.
* @retval ::NRF_ERROR_INVALID_ADDR if parameter address is outside of the flash size.
* @retval ::NRF_ERROR_NO_MEM if no parameter page is provided (see SoftDevice Specification for more info)
*/
typedef struct
{
uint32_t address; /**< The base address of the interrupt vector table for forwarded interrupts.*/
} sd_mbr_command_vector_table_base_set_t;
/**@brief Sets the base address of the interrupt vector table for interrupts forwarded from the MBR
*
* Unlike sd_mbr_command_vector_table_base_set_t, this function does not reset, and it does not
* change where the MBR starts after reset.
*
* @retval ::NRF_SUCCESS
*/
typedef struct
{
uint32_t address; /**< The base address of the interrupt vector table for forwarded interrupts.*/
} sd_mbr_command_irq_forward_address_set_t;
/**@brief Input structure containing data used when calling ::sd_mbr_command
*
* Depending on what command value that is set, the corresponding params value type must also be
* set. See @ref NRF_MBR_COMMANDS for command types and corresponding params value type. If command
* @ref SD_MBR_COMMAND_INIT_SD is set, it is not necessary to set any values under params.
*/
typedef struct
{
uint32_t command; /**< Type of command to be issued. See @ref NRF_MBR_COMMANDS. */
union
{
sd_mbr_command_copy_sd_t copy_sd; /**< Parameters for copy SoftDevice.*/
sd_mbr_command_compare_t compare; /**< Parameters for verify.*/
sd_mbr_command_copy_bl_t copy_bl; /**< Parameters for copy BootLoader. Requires parameter page. */
sd_mbr_command_vector_table_base_set_t base_set; /**< Parameters for vector table base set. Requires parameter page.*/
sd_mbr_command_irq_forward_address_set_t irq_forward_address_set; /**< Parameters for irq forward address set*/
} params; /**< Command parameters. */
} sd_mbr_command_t;
/** @} */
/** @addtogroup NRF_MBR_FUNCTIONS Functions
* @{ */
/**@brief Issue Master Boot Record commands
*
* Commands used when updating a SoftDevice and bootloader.
*
* The @ref SD_MBR_COMMAND_COPY_BL and @ref SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET requires
* parameters to be retained by the MBR when resetting the IC. This is done in a separate flash
* page provided by the application. The UICR register UICR.NRFFW[1] must be set to an address
* corresponding to a page in the application flash space. This page will be cleared by the MBR and
* used to store the command before reset. When the UICR.NRFFW[1] field is set the page it refers
* to must not be used by the application. If the UICR.NRFFW[1] is set to 0xFFFFFFFF (the default)
* MBR commands which use flash will be unavailable and return @ref NRF_ERROR_NO_MEM.
*
* @param[in] param Pointer to a struct describing the command.
*
* @note For return values, see ::sd_mbr_command_copy_sd_t, ::sd_mbr_command_copy_bl_t,
* ::sd_mbr_command_compare_t, ::sd_mbr_command_vector_table_base_set_t,
* ::sd_mbr_command_irq_forward_address_set_t
*
* @retval ::NRF_ERROR_NO_MEM if UICR.NRFFW[1] is not set (i.e. is 0xFFFFFFFF).
* @retval ::NRF_ERROR_INVALID_PARAM if an invalid command is given.
*/
SVCALL(SD_MBR_COMMAND, uint32_t, sd_mbr_command(sd_mbr_command_t* param));
/** @} */
#ifdef __cplusplus
}
#endif
#endif // NRF_MBR_H__
/**
@}
*/

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2014 - 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.
*/
/**
@defgroup nrf_error SoftDevice Global Error Codes
@{
@brief Global Error definitions
*/
/* Header guard */
#ifndef NRF_ERROR_H__
#define NRF_ERROR_H__
#ifdef __cplusplus
extern "C" {
#endif
/** @defgroup NRF_ERRORS_BASE Error Codes Base number definitions
* @{ */
#define NRF_ERROR_BASE_NUM (0x0) ///< Global error base
#define NRF_ERROR_SDM_BASE_NUM (0x1000) ///< SDM error base
#define NRF_ERROR_SOC_BASE_NUM (0x2000) ///< SoC error base
#define NRF_ERROR_STK_BASE_NUM (0x3000) ///< STK error base
/** @} */
#define NRF_SUCCESS (NRF_ERROR_BASE_NUM + 0) ///< Successful command
#define NRF_ERROR_SVC_HANDLER_MISSING (NRF_ERROR_BASE_NUM + 1) ///< SVC handler is missing
#define NRF_ERROR_SOFTDEVICE_NOT_ENABLED (NRF_ERROR_BASE_NUM + 2) ///< SoftDevice has not been enabled
#define NRF_ERROR_INTERNAL (NRF_ERROR_BASE_NUM + 3) ///< Internal Error
#define NRF_ERROR_NO_MEM (NRF_ERROR_BASE_NUM + 4) ///< No Memory for operation
#define NRF_ERROR_NOT_FOUND (NRF_ERROR_BASE_NUM + 5) ///< Not found
#define NRF_ERROR_NOT_SUPPORTED (NRF_ERROR_BASE_NUM + 6) ///< Not supported
#define NRF_ERROR_INVALID_PARAM (NRF_ERROR_BASE_NUM + 7) ///< Invalid Parameter
#define NRF_ERROR_INVALID_STATE (NRF_ERROR_BASE_NUM + 8) ///< Invalid state, operation disallowed in this state
#define NRF_ERROR_INVALID_LENGTH (NRF_ERROR_BASE_NUM + 9) ///< Invalid Length
#define NRF_ERROR_INVALID_FLAGS (NRF_ERROR_BASE_NUM + 10) ///< Invalid Flags
#define NRF_ERROR_INVALID_DATA (NRF_ERROR_BASE_NUM + 11) ///< Invalid Data
#define NRF_ERROR_DATA_SIZE (NRF_ERROR_BASE_NUM + 12) ///< Invalid Data size
#define NRF_ERROR_TIMEOUT (NRF_ERROR_BASE_NUM + 13) ///< Operation timed out
#define NRF_ERROR_NULL (NRF_ERROR_BASE_NUM + 14) ///< Null Pointer
#define NRF_ERROR_FORBIDDEN (NRF_ERROR_BASE_NUM + 15) ///< Forbidden Operation
#define NRF_ERROR_INVALID_ADDR (NRF_ERROR_BASE_NUM + 16) ///< Bad Memory Address
#define NRF_ERROR_BUSY (NRF_ERROR_BASE_NUM + 17) ///< Busy
#define NRF_ERROR_CONN_COUNT (NRF_ERROR_BASE_NUM + 18) ///< Maximum connection count exceeded.
#define NRF_ERROR_RESOURCES (NRF_ERROR_BASE_NUM + 19) ///< Not enough resources for operation
#ifdef __cplusplus
}
#endif
#endif // NRF_ERROR_H__
/**
@}
*/

View File

@ -0,0 +1,70 @@
/*
* 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.
*/
/**
@addtogroup nrf_sdm_api
@{
@defgroup nrf_sdm_error SoftDevice Manager Error Codes
@{
@brief Error definitions for the SDM API
*/
/* Header guard */
#ifndef NRF_ERROR_SDM_H__
#define NRF_ERROR_SDM_H__
#include "nrf_error.h"
#ifdef __cplusplus
extern "C" {
#endif
#define NRF_ERROR_SDM_LFCLK_SOURCE_UNKNOWN (NRF_ERROR_SDM_BASE_NUM + 0) ///< Unknown LFCLK source.
#define NRF_ERROR_SDM_INCORRECT_INTERRUPT_CONFIGURATION (NRF_ERROR_SDM_BASE_NUM + 1) ///< Incorrect interrupt configuration (can be caused by using illegal priority levels, or having enabled SoftDevice interrupts).
#define NRF_ERROR_SDM_INCORRECT_CLENR0 (NRF_ERROR_SDM_BASE_NUM + 2) ///< Incorrect CLENR0 (can be caused by erroneous SoftDevice flashing).
#ifdef __cplusplus
}
#endif
#endif // NRF_ERROR_SDM_H__
/**
@}
@}
*/

View File

@ -0,0 +1,85 @@
/*
* 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.
*/
/**
@addtogroup nrf_soc_api
@{
@defgroup nrf_soc_error SoC Library Error Codes
@{
@brief Error definitions for the SoC library
*/
/* Header guard */
#ifndef NRF_ERROR_SOC_H__
#define NRF_ERROR_SOC_H__
#include "nrf_error.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Mutex Errors */
#define NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN (NRF_ERROR_SOC_BASE_NUM + 0) ///< Mutex already taken
/* NVIC errors */
#define NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE (NRF_ERROR_SOC_BASE_NUM + 1) ///< NVIC interrupt not available
#define NRF_ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED (NRF_ERROR_SOC_BASE_NUM + 2) ///< NVIC interrupt priority not allowed
#define NRF_ERROR_SOC_NVIC_SHOULD_NOT_RETURN (NRF_ERROR_SOC_BASE_NUM + 3) ///< NVIC should not return
/* Power errors */
#define NRF_ERROR_SOC_POWER_MODE_UNKNOWN (NRF_ERROR_SOC_BASE_NUM + 4) ///< Power mode unknown
#define NRF_ERROR_SOC_POWER_POF_THRESHOLD_UNKNOWN (NRF_ERROR_SOC_BASE_NUM + 5) ///< Power POF threshold unknown
#define NRF_ERROR_SOC_POWER_OFF_SHOULD_NOT_RETURN (NRF_ERROR_SOC_BASE_NUM + 6) ///< Power off should not return
/* Rand errors */
#define NRF_ERROR_SOC_RAND_NOT_ENOUGH_VALUES (NRF_ERROR_SOC_BASE_NUM + 7) ///< RAND not enough values
/* PPI errors */
#define NRF_ERROR_SOC_PPI_INVALID_CHANNEL (NRF_ERROR_SOC_BASE_NUM + 8) ///< Invalid PPI Channel
#define NRF_ERROR_SOC_PPI_INVALID_GROUP (NRF_ERROR_SOC_BASE_NUM + 9) ///< Invalid PPI Group
#ifdef __cplusplus
}
#endif
#endif // NRF_ERROR_SOC_H__
/**
@}
@}
*/

View File

@ -0,0 +1,486 @@
/*
* Copyright (c) 2016 - 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.
*/
/**
* @defgroup nrf_nvic_api SoftDevice NVIC API
* @{
*
* @note In order to use this module, the following code has to be added to a .c file:
* \code
* nrf_nvic_state_t nrf_nvic_state = {0};
* \endcode
*
* @note Definitions and declarations starting with __ (double underscore) in this header file are
* not intended for direct use by the application.
*
* @brief APIs for the accessing NVIC when using a SoftDevice.
*
*/
#ifndef NRF_NVIC_H__
#define NRF_NVIC_H__
#include <stdint.h>
#include "nrf.h"
#include "nrf_svc.h"
#include "nrf_error.h"
#include "nrf_error_soc.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@addtogroup NRF_NVIC_DEFINES Defines
* @{ */
/**@defgroup NRF_NVIC_ISER_DEFINES SoftDevice NVIC internal definitions
* @{ */
#define __NRF_NVIC_NVMC_IRQn (30) /**< The peripheral ID of the NVMC. IRQ numbers are used to identify peripherals, but the NVMC doesn't have an IRQ number in the MDK. */
#define __NRF_NVIC_ISER_COUNT (2) /**< The number of ISER/ICER registers in the NVIC that are used. */
/**@brief Interrupts used by the SoftDevice, with IRQn in the range 0-31. */
#define __NRF_NVIC_SD_IRQS_0 ((uint32_t)( \
(1U << POWER_CLOCK_IRQn) \
| (1U << RADIO_IRQn) \
| (1U << RTC0_IRQn) \
| (1U << TIMER0_IRQn) \
| (1U << RNG_IRQn) \
| (1U << ECB_IRQn) \
| (1U << CCM_AAR_IRQn) \
| (1U << TEMP_IRQn) \
| (1U << __NRF_NVIC_NVMC_IRQn) \
| (1U << (uint32_t)SWI5_IRQn) \
))
/**@brief Interrupts used by the SoftDevice, with IRQn in the range 32-63. */
#define __NRF_NVIC_SD_IRQS_1 ((uint32_t)0)
/**@brief Interrupts available for to application, with IRQn in the range 0-31. */
#define __NRF_NVIC_APP_IRQS_0 (~__NRF_NVIC_SD_IRQS_0)
/**@brief Interrupts available for to application, with IRQn in the range 32-63. */
#define __NRF_NVIC_APP_IRQS_1 (~__NRF_NVIC_SD_IRQS_1)
/**@} */
/**@} */
/**@addtogroup NRF_NVIC_VARIABLES Variables
* @{ */
/**@brief Type representing the state struct for the SoftDevice NVIC module. */
typedef struct
{
uint32_t volatile __irq_masks[__NRF_NVIC_ISER_COUNT]; /**< IRQs enabled by the application in the NVIC. */
uint32_t volatile __cr_flag; /**< Non-zero if already in a critical region */
} nrf_nvic_state_t;
/**@brief Variable keeping the state for the SoftDevice NVIC module. This must be declared in an
* application source file. */
extern nrf_nvic_state_t nrf_nvic_state;
/**@} */
/**@addtogroup NRF_NVIC_INTERNAL_FUNCTIONS SoftDevice NVIC internal functions
* @{ */
/**@brief Disables IRQ interrupts globally, including the SoftDevice's interrupts.
*
* @retval The value of PRIMASK prior to disabling the interrupts.
*/
__STATIC_INLINE int __sd_nvic_irq_disable(void);
/**@brief Enables IRQ interrupts globally, including the SoftDevice's interrupts.
*/
__STATIC_INLINE void __sd_nvic_irq_enable(void);
/**@brief Checks if IRQn is available to application
* @param[in] IRQn IRQ to check
*
* @retval 1 (true) if the IRQ to check is available to the application
*/
__STATIC_INLINE uint32_t __sd_nvic_app_accessible_irq(IRQn_Type IRQn);
/**@brief Checks if priority is available to application
* @param[in] priority priority to check
*
* @retval 1 (true) if the priority to check is available to the application
*/
__STATIC_INLINE uint32_t __sd_nvic_is_app_accessible_priority(uint32_t priority);
/**@} */
/**@addtogroup NRF_NVIC_FUNCTIONS SoftDevice NVIC public functions
* @{ */
/**@brief Enable External Interrupt.
* @note Corresponds to NVIC_EnableIRQ in CMSIS.
*
* @pre IRQn is valid and not reserved by the stack.
*
* @param[in] IRQn See the NVIC_EnableIRQ documentation in CMSIS.
*
* @retval ::NRF_SUCCESS The interrupt was enabled.
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE The interrupt is not available for the application.
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED The interrupt has a priority not available for the application.
*/
__STATIC_INLINE uint32_t sd_nvic_EnableIRQ(IRQn_Type IRQn);
/**@brief Disable External Interrupt.
* @note Corresponds to NVIC_DisableIRQ in CMSIS.
*
* @pre IRQn is valid and not reserved by the stack.
*
* @param[in] IRQn See the NVIC_DisableIRQ documentation in CMSIS.
*
* @retval ::NRF_SUCCESS The interrupt was disabled.
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE The interrupt is not available for the application.
*/
__STATIC_INLINE uint32_t sd_nvic_DisableIRQ(IRQn_Type IRQn);
/**@brief Get Pending Interrupt.
* @note Corresponds to NVIC_GetPendingIRQ in CMSIS.
*
* @pre IRQn is valid and not reserved by the stack.
*
* @param[in] IRQn See the NVIC_GetPendingIRQ documentation in CMSIS.
* @param[out] p_pending_irq Return value from NVIC_GetPendingIRQ.
*
* @retval ::NRF_SUCCESS The interrupt is available for the application.
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE IRQn is not available for the application.
*/
__STATIC_INLINE uint32_t sd_nvic_GetPendingIRQ(IRQn_Type IRQn, uint32_t * p_pending_irq);
/**@brief Set Pending Interrupt.
* @note Corresponds to NVIC_SetPendingIRQ in CMSIS.
*
* @pre IRQn is valid and not reserved by the stack.
*
* @param[in] IRQn See the NVIC_SetPendingIRQ documentation in CMSIS.
*
* @retval ::NRF_SUCCESS The interrupt is set pending.
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE IRQn is not available for the application.
*/
__STATIC_INLINE uint32_t sd_nvic_SetPendingIRQ(IRQn_Type IRQn);
/**@brief Clear Pending Interrupt.
* @note Corresponds to NVIC_ClearPendingIRQ in CMSIS.
*
* @pre IRQn is valid and not reserved by the stack.
*
* @param[in] IRQn See the NVIC_ClearPendingIRQ documentation in CMSIS.
*
* @retval ::NRF_SUCCESS The interrupt pending flag is cleared.
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE IRQn is not available for the application.
*/
__STATIC_INLINE uint32_t sd_nvic_ClearPendingIRQ(IRQn_Type IRQn);
/**@brief Set Interrupt Priority.
* @note Corresponds to NVIC_SetPriority in CMSIS.
*
* @pre IRQn is valid and not reserved by the stack.
* @pre Priority is valid and not reserved by the stack.
*
* @param[in] IRQn See the NVIC_SetPriority documentation in CMSIS.
* @param[in] priority A valid IRQ priority for use by the application.
*
* @retval ::NRF_SUCCESS The interrupt and priority level is available for the application.
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE IRQn is not available for the application.
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED The interrupt priority is not available for the application.
*/
__STATIC_INLINE uint32_t sd_nvic_SetPriority(IRQn_Type IRQn, uint32_t priority);
/**@brief Get Interrupt Priority.
* @note Corresponds to NVIC_GetPriority in CMSIS.
*
* @pre IRQn is valid and not reserved by the stack.
*
* @param[in] IRQn See the NVIC_GetPriority documentation in CMSIS.
* @param[out] p_priority Return value from NVIC_GetPriority.
*
* @retval ::NRF_SUCCESS The interrupt priority is returned in p_priority.
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE - IRQn is not available for the application.
*/
__STATIC_INLINE uint32_t sd_nvic_GetPriority(IRQn_Type IRQn, uint32_t * p_priority);
/**@brief System Reset.
* @note Corresponds to NVIC_SystemReset in CMSIS.
*
* @retval ::NRF_ERROR_SOC_NVIC_SHOULD_NOT_RETURN
*/
__STATIC_INLINE uint32_t sd_nvic_SystemReset(void);
/**@brief Enter critical region.
*
* @post Application interrupts will be disabled.
* @note sd_nvic_critical_region_enter() and ::sd_nvic_critical_region_exit() must be called in matching pairs inside each
* execution context
* @sa sd_nvic_critical_region_exit
*
* @param[out] p_is_nested_critical_region If 1, the application is now in a nested critical region.
*
* @retval ::NRF_SUCCESS
*/
__STATIC_INLINE uint32_t sd_nvic_critical_region_enter(uint8_t * p_is_nested_critical_region);
/**@brief Exit critical region.
*
* @pre Application has entered a critical region using ::sd_nvic_critical_region_enter.
* @post If not in a nested critical region, the application interrupts will restored to the state before ::sd_nvic_critical_region_enter was called.
*
* @param[in] is_nested_critical_region If this is set to 1, the critical region won't be exited. @sa sd_nvic_critical_region_enter.
*
* @retval ::NRF_SUCCESS
*/
__STATIC_INLINE uint32_t sd_nvic_critical_region_exit(uint8_t is_nested_critical_region);
/**@} */
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE int __sd_nvic_irq_disable(void)
{
int pm = __get_PRIMASK();
__disable_irq();
return pm;
}
__STATIC_INLINE void __sd_nvic_irq_enable(void)
{
__enable_irq();
}
__STATIC_INLINE uint32_t __sd_nvic_app_accessible_irq(IRQn_Type IRQn)
{
if (IRQn < 32)
{
return ((1UL<<IRQn) & __NRF_NVIC_APP_IRQS_0) != 0;
}
else if (IRQn < 64)
{
return ((1UL<<(IRQn-32)) & __NRF_NVIC_APP_IRQS_1) != 0;
}
else
{
return 1;
}
}
__STATIC_INLINE uint32_t __sd_nvic_is_app_accessible_priority(uint32_t priority)
{
if(priority >= (1 << __NVIC_PRIO_BITS))
{
return 0;
}
if( priority == 0
|| priority == 1
|| priority == 4
)
{
return 0;
}
return 1;
}
__STATIC_INLINE uint32_t sd_nvic_EnableIRQ(IRQn_Type IRQn)
{
if (!__sd_nvic_app_accessible_irq(IRQn))
{
return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE;
}
if (!__sd_nvic_is_app_accessible_priority(NVIC_GetPriority(IRQn)))
{
return NRF_ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED;
}
if (nrf_nvic_state.__cr_flag)
{
nrf_nvic_state.__irq_masks[(uint32_t)((int32_t)IRQn) >> 5] |= (uint32_t)(1 << ((uint32_t)((int32_t)IRQn) & (uint32_t)0x1F));
}
else
{
NVIC_EnableIRQ(IRQn);
}
return NRF_SUCCESS;
}
__STATIC_INLINE uint32_t sd_nvic_DisableIRQ(IRQn_Type IRQn)
{
if (!__sd_nvic_app_accessible_irq(IRQn))
{
return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE;
}
if (nrf_nvic_state.__cr_flag)
{
nrf_nvic_state.__irq_masks[(uint32_t)((int32_t)IRQn) >> 5] &= ~(1UL << ((uint32_t)(IRQn) & 0x1F));
}
else
{
NVIC_DisableIRQ(IRQn);
}
return NRF_SUCCESS;
}
__STATIC_INLINE uint32_t sd_nvic_GetPendingIRQ(IRQn_Type IRQn, uint32_t * p_pending_irq)
{
if (__sd_nvic_app_accessible_irq(IRQn))
{
*p_pending_irq = NVIC_GetPendingIRQ(IRQn);
return NRF_SUCCESS;
}
else
{
return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE;
}
}
__STATIC_INLINE uint32_t sd_nvic_SetPendingIRQ(IRQn_Type IRQn)
{
if (__sd_nvic_app_accessible_irq(IRQn))
{
NVIC_SetPendingIRQ(IRQn);
return NRF_SUCCESS;
}
else
{
return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE;
}
}
__STATIC_INLINE uint32_t sd_nvic_ClearPendingIRQ(IRQn_Type IRQn)
{
if (__sd_nvic_app_accessible_irq(IRQn))
{
NVIC_ClearPendingIRQ(IRQn);
return NRF_SUCCESS;
}
else
{
return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE;
}
}
__STATIC_INLINE uint32_t sd_nvic_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
if (!__sd_nvic_app_accessible_irq(IRQn))
{
return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE;
}
if (!__sd_nvic_is_app_accessible_priority(priority))
{
return NRF_ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED;
}
NVIC_SetPriority(IRQn, (uint32_t)priority);
return NRF_SUCCESS;
}
__STATIC_INLINE uint32_t sd_nvic_GetPriority(IRQn_Type IRQn, uint32_t * p_priority)
{
if (__sd_nvic_app_accessible_irq(IRQn))
{
*p_priority = (NVIC_GetPriority(IRQn) & 0xFF);
return NRF_SUCCESS;
}
else
{
return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE;
}
}
__STATIC_INLINE uint32_t sd_nvic_SystemReset(void)
{
NVIC_SystemReset();
return NRF_ERROR_SOC_NVIC_SHOULD_NOT_RETURN;
}
__STATIC_INLINE uint32_t sd_nvic_critical_region_enter(uint8_t * p_is_nested_critical_region)
{
int was_masked = __sd_nvic_irq_disable();
if (!nrf_nvic_state.__cr_flag)
{
nrf_nvic_state.__cr_flag = 1;
nrf_nvic_state.__irq_masks[0] = ( NVIC->ICER[0] & __NRF_NVIC_APP_IRQS_0 );
NVIC->ICER[0] = __NRF_NVIC_APP_IRQS_0;
nrf_nvic_state.__irq_masks[1] = ( NVIC->ICER[1] & __NRF_NVIC_APP_IRQS_1 );
NVIC->ICER[1] = __NRF_NVIC_APP_IRQS_1;
*p_is_nested_critical_region = 0;
}
else
{
*p_is_nested_critical_region = 1;
}
if (!was_masked)
{
__sd_nvic_irq_enable();
}
return NRF_SUCCESS;
}
__STATIC_INLINE uint32_t sd_nvic_critical_region_exit(uint8_t is_nested_critical_region)
{
if (nrf_nvic_state.__cr_flag && (is_nested_critical_region == 0))
{
int was_masked = __sd_nvic_irq_disable();
NVIC->ISER[0] = nrf_nvic_state.__irq_masks[0];
NVIC->ISER[1] = nrf_nvic_state.__irq_masks[1];
nrf_nvic_state.__cr_flag = 0;
if (!was_masked)
{
__sd_nvic_irq_enable();
}
}
return NRF_SUCCESS;
}
#endif /* SUPPRESS_INLINE_IMPLEMENTATION */
#ifdef __cplusplus
}
#endif
#endif // NRF_NVIC_H__
/**@} */

View File

@ -0,0 +1,59 @@
/**
* 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 NRF_SD_DEF_H__
#define NRF_SD_DEF_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SD_PPI_CHANNELS_USED 0xFFFE0000uL /**< PPI channels utilized by SotfDevice (not available to the application). */
#define SD_PPI_GROUPS_USED 0x0000000CuL /**< PPI groups utilized by SoftDevice (not available to the application). */
#define SD_TIMERS_USED 0x00000001uL /**< Timers used by SoftDevice. */
#define SD_SWI_USED 0x0000003CuL /**< Software interrupts used by SoftDevice */
#ifdef __cplusplus
}
#endif
#endif /* NRF_SD_DEF_H__ */

View File

@ -0,0 +1,358 @@
/*
* Copyright (c) 2015 - 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.
*/
/**
@defgroup nrf_sdm_api SoftDevice Manager API
@{
@brief APIs for SoftDevice management.
*/
#ifndef NRF_SDM_H__
#define NRF_SDM_H__
#include <stdint.h>
#include "nrf.h"
#include "nrf_svc.h"
#include "nrf_error.h"
#include "nrf_error_sdm.h"
#include "nrf_soc.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @addtogroup NRF_SDM_DEFINES Defines
* @{ */
#ifdef NRFSOC_DOXYGEN
/// Declared in nrf_mbr.h
#define MBR_SIZE 0
#warning test
#endif
/** @brief The major version for the SoftDevice binary distributed with this header file. */
#define SD_MAJOR_VERSION (6)
/** @brief The minor version for the SoftDevice binary distributed with this header file. */
#define SD_MINOR_VERSION (0)
/** @brief The bugfix version for the SoftDevice binary distributed with this header file. */
#define SD_BUGFIX_VERSION (0)
/** @brief The full version number for the SoftDevice binary this header file was distributed
* with, as a decimal number in the form Mmmmbbb, where:
* - M is major version (one or more digits)
* - mmm is minor version (three digits)
* - bbb is bugfix version (three digits). */
#define SD_VERSION (SD_MAJOR_VERSION * 1000000 + SD_MINOR_VERSION * 1000 + SD_BUGFIX_VERSION)
/** @brief SoftDevice Manager SVC Base number. */
#define SDM_SVC_BASE 0x10
/** @brief SoftDevice unique string size in bytes. */
#define SD_UNIQUE_STR_SIZE 20
/** @brief Invalid info field. Returned when an info field does not exist. */
#define SDM_INFO_FIELD_INVALID (0)
/** @brief Defines the SoftDevice Information Structure location (address) as an offset from
the start of the SoftDevice (without MBR)*/
#define SOFTDEVICE_INFO_STRUCT_OFFSET (0x2000)
/** @brief Defines the absolute SoftDevice Information Structure location (address) when the
* SoftDevice is installed just above the MBR (the usual case). */
#define SOFTDEVICE_INFO_STRUCT_ADDRESS (SOFTDEVICE_INFO_STRUCT_OFFSET + MBR_SIZE)
/** @brief Defines the offset for the SoftDevice Information Structure size value relative to the
* SoftDevice base address. The size value is of type uint8_t. */
#define SD_INFO_STRUCT_SIZE_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET)
/** @brief Defines the offset for the SoftDevice size value relative to the SoftDevice base address.
* The size value is of type uint32_t. */
#define SD_SIZE_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET + 0x08)
/** @brief Defines the offset for FWID value relative to the SoftDevice base address. The FWID value
* is of type uint16_t. */
#define SD_FWID_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET + 0x0C)
/** @brief Defines the offset for the SoftDevice ID relative to the SoftDevice base address. The ID
* is of type uint32_t. */
#define SD_ID_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET + 0x10)
/** @brief Defines the offset for the SoftDevice version relative to the SoftDevice base address in
* the same format as @ref SD_VERSION, stored as an uint32_t. */
#define SD_VERSION_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET + 0x14)
/** @brief Defines the offset for the SoftDevice unique string relative to the SoftDevice base address.
* The SD_UNIQUE_STR is stored as an array of uint8_t. The size of array is @ref SD_UNIQUE_STR_SIZE.
*/
#define SD_UNIQUE_STR_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET + 0x18)
/** @brief Defines a macro for retrieving the actual SoftDevice Information Structure size value
* from a given base address. Use @ref MBR_SIZE as the argument when the SoftDevice is
* installed just above the MBR (the usual case). */
#define SD_INFO_STRUCT_SIZE_GET(baseaddr) (*((uint8_t *) ((baseaddr) + SD_INFO_STRUCT_SIZE_OFFSET)))
/** @brief Defines a macro for retrieving the actual SoftDevice size value from a given base
* address. Use @ref MBR_SIZE as the argument when the SoftDevice is installed just above
* the MBR (the usual case). */
#define SD_SIZE_GET(baseaddr) (*((uint32_t *) ((baseaddr) + SD_SIZE_OFFSET)))
/** @brief Defines a macro for retrieving the actual FWID value from a given base address. Use
* @ref MBR_SIZE as the argument when the SoftDevice is installed just above the MBR (the usual
* case). */
#define SD_FWID_GET(baseaddr) (*((uint16_t *) ((baseaddr) + SD_FWID_OFFSET)))
/** @brief Defines a macro for retrieving the actual SoftDevice ID from a given base address. Use
* @ref MBR_SIZE as the argument when the SoftDevice is installed just above the MBR (the
* usual case). */
#define SD_ID_GET(baseaddr) ((SD_INFO_STRUCT_SIZE_GET(baseaddr) > (SD_ID_OFFSET - SOFTDEVICE_INFO_STRUCT_OFFSET)) \
? (*((uint32_t *) ((baseaddr) + SD_ID_OFFSET))) : SDM_INFO_FIELD_INVALID)
/** @brief Defines a macro for retrieving the actual SoftDevice version from a given base address.
* Use @ref MBR_SIZE as the argument when the SoftDevice is installed just above the MBR
* (the usual case). */
#define SD_VERSION_GET(baseaddr) ((SD_INFO_STRUCT_SIZE_GET(baseaddr) > (SD_VERSION_OFFSET - SOFTDEVICE_INFO_STRUCT_OFFSET)) \
? (*((uint32_t *) ((baseaddr) + SD_VERSION_OFFSET))) : SDM_INFO_FIELD_INVALID)
/** @brief Defines a macro for retrieving the address of SoftDevice unique str based on a given base address.
* Use @ref MBR_SIZE as the argument when the SoftDevice is installed just above the MBR
* (the usual case). */
#define SD_UNIQUE_STR_ADDR_GET(baseaddr) ((SD_INFO_STRUCT_SIZE_GET(baseaddr) > (SD_UNIQUE_STR_OFFSET - SOFTDEVICE_INFO_STRUCT_OFFSET)) \
? (((uint8_t *) ((baseaddr) + SD_UNIQUE_STR_OFFSET))) : SDM_INFO_FIELD_INVALID)
/**@defgroup NRF_FAULT_ID_RANGES Fault ID ranges
* @{ */
#define NRF_FAULT_ID_SD_RANGE_START 0x00000000 /**< SoftDevice ID range start. */
#define NRF_FAULT_ID_APP_RANGE_START 0x00001000 /**< Application ID range start. */
/**@} */
/**@defgroup NRF_FAULT_IDS Fault ID types
* @{ */
#define NRF_FAULT_ID_SD_ASSERT (NRF_FAULT_ID_SD_RANGE_START + 1) /**< SoftDevice assertion. The info parameter is reserved for future used. */
#define NRF_FAULT_ID_APP_MEMACC (NRF_FAULT_ID_APP_RANGE_START + 1) /**< Application invalid memory access. The info parameter will contain 0x00000000,
in case of SoftDevice RAM access violation. In case of SoftDevice peripheral
register violation the info parameter will contain the sub-region number of
PREGION[0], on whose address range the disallowed write access caused the
memory access fault. */
/**@} */
/** @} */
/** @addtogroup NRF_SDM_ENUMS Enumerations
* @{ */
/**@brief nRF SoftDevice Manager API SVC numbers. */
enum NRF_SD_SVCS
{
SD_SOFTDEVICE_ENABLE = SDM_SVC_BASE, /**< ::sd_softdevice_enable */
SD_SOFTDEVICE_DISABLE, /**< ::sd_softdevice_disable */
SD_SOFTDEVICE_IS_ENABLED, /**< ::sd_softdevice_is_enabled */
SD_SOFTDEVICE_VECTOR_TABLE_BASE_SET, /**< ::sd_softdevice_vector_table_base_set */
SVC_SDM_LAST /**< Placeholder for last SDM SVC */
};
/** @} */
/** @addtogroup NRF_SDM_DEFINES Defines
* @{ */
/**@defgroup NRF_CLOCK_LF_ACCURACY Clock accuracy
* @{ */
#define NRF_CLOCK_LF_ACCURACY_250_PPM (0) /**< Default: 250 ppm */
#define NRF_CLOCK_LF_ACCURACY_500_PPM (1) /**< 500 ppm */
#define NRF_CLOCK_LF_ACCURACY_150_PPM (2) /**< 150 ppm */
#define NRF_CLOCK_LF_ACCURACY_100_PPM (3) /**< 100 ppm */
#define NRF_CLOCK_LF_ACCURACY_75_PPM (4) /**< 75 ppm */
#define NRF_CLOCK_LF_ACCURACY_50_PPM (5) /**< 50 ppm */
#define NRF_CLOCK_LF_ACCURACY_30_PPM (6) /**< 30 ppm */
#define NRF_CLOCK_LF_ACCURACY_20_PPM (7) /**< 20 ppm */
#define NRF_CLOCK_LF_ACCURACY_10_PPM (8) /**< 10 ppm */
#define NRF_CLOCK_LF_ACCURACY_5_PPM (9) /**< 5 ppm */
#define NRF_CLOCK_LF_ACCURACY_2_PPM (10) /**< 2 ppm */
#define NRF_CLOCK_LF_ACCURACY_1_PPM (11) /**< 1 ppm */
/** @} */
/**@defgroup NRF_CLOCK_LF_SRC Possible LFCLK oscillator sources
* @{ */
#define NRF_CLOCK_LF_SRC_RC (0) /**< LFCLK RC oscillator. */
#define NRF_CLOCK_LF_SRC_XTAL (1) /**< LFCLK crystal oscillator. */
#define NRF_CLOCK_LF_SRC_SYNTH (2) /**< LFCLK Synthesized from HFCLK. */
/** @} */
/** @} */
/** @addtogroup NRF_SDM_TYPES Types
* @{ */
/**@brief Type representing LFCLK oscillator source. */
typedef struct
{
uint8_t source; /**< LF oscillator clock source, see @ref NRF_CLOCK_LF_SRC. */
uint8_t rc_ctiv; /**< Only for ::NRF_CLOCK_LF_SRC_RC: Calibration timer interval in 1/4 second
units (nRF52: 1-32).
@note To avoid excessive clock drift, 0.5 degrees Celsius is the
maximum temperature change allowed in one calibration timer
interval. The interval should be selected to ensure this.
@note Must be 0 if source is not ::NRF_CLOCK_LF_SRC_RC. */
uint8_t rc_temp_ctiv; /**< Only for ::NRF_CLOCK_LF_SRC_RC: How often (in number of calibration
intervals) the RC oscillator shall be calibrated if the temperature
hasn't changed.
0: Always calibrate even if the temperature hasn't changed.
1: Only calibrate if the temperature has changed (legacy - nRF51 only).
2-33: Check the temperature and only calibrate if it has changed,
however calibration will take place every rc_temp_ctiv
intervals in any case.
@note Must be 0 if source is not ::NRF_CLOCK_LF_SRC_RC.
@note For nRF52, the application must ensure calibration at least once
every 8 seconds to ensure +/-500 ppm clock stability. The
recommended configuration for ::NRF_CLOCK_LF_SRC_RC on nRF52 is
rc_ctiv=16 and rc_temp_ctiv=2. This will ensure calibration at
least once every 8 seconds and for temperature changes of 0.5
degrees Celsius every 4 seconds. See the Product Specification
for the nRF52 device being used for more information.*/
uint8_t accuracy; /**< External clock accuracy used in the LL to compute timing
windows, see @ref NRF_CLOCK_LF_ACCURACY.*/
} nrf_clock_lf_cfg_t;
/**@brief Fault Handler type.
*
* When certain unrecoverable errors occur within the application or SoftDevice the fault handler will be called back.
* The protocol stack will be in an undefined state when this happens and the only way to recover will be to
* perform a reset, using e.g. CMSIS NVIC_SystemReset().
* If the application returns from the fault handler the SoftDevice will call NVIC_SystemReset().
*
* @note This callback is executed in HardFault context, thus SVC functions cannot be called from the fault callback.
*
* @param[in] id Fault identifier. See @ref NRF_FAULT_IDS.
* @param[in] pc The program counter of the instruction that triggered the fault.
* @param[in] info Optional additional information regarding the fault. Refer to each Fault identifier for details.
*
* @note When id is set to @ref NRF_FAULT_ID_APP_MEMACC, pc will contain the address of the instruction being executed at the time when
* the fault is detected by the CPU. The CPU program counter may have advanced up to 2 instructions (no branching) after the one that triggered the fault.
*/
typedef void (*nrf_fault_handler_t)(uint32_t id, uint32_t pc, uint32_t info);
/** @} */
/** @addtogroup NRF_SDM_FUNCTIONS Functions
* @{ */
/**@brief Enables the SoftDevice and by extension the protocol stack.
*
* @note Some care must be taken if a low frequency clock source is already running when calling this function:
* If the LF clock has a different source then the one currently running, it will be stopped. Then, the new
* clock source will be started.
*
* @note This function has no effect when returning with an error.
*
* @post If return code is ::NRF_SUCCESS
* - SoC library and protocol stack APIs are made available.
* - A portion of RAM will be unavailable (see relevant SDS documentation).
* - Some peripherals will be unavailable or available only through the SoC API (see relevant SDS documentation).
* - Interrupts will not arrive from protected peripherals or interrupts.
* - nrf_nvic_ functions must be used instead of CMSIS NVIC_ functions for reliable usage of the SoftDevice.
* - Interrupt latency may be affected by the SoftDevice (see relevant SDS documentation).
* - Chosen low frequency clock source will be running.
*
* @param p_clock_lf_cfg Low frequency clock source and accuracy.
If NULL the clock will be configured as an RC source with rc_ctiv = 16 and .rc_temp_ctiv = 2
In the case of XTAL source, the PPM accuracy of the chosen clock source must be greater than or equal to the actual characteristics of your XTAL clock.
* @param fault_handler Callback to be invoked in case of fault, cannot be NULL.
*
* @retval ::NRF_SUCCESS
* @retval ::NRF_ERROR_INVALID_ADDR Invalid or NULL pointer supplied.
* @retval ::NRF_ERROR_INVALID_STATE SoftDevice is already enabled, and the clock source and fault handler cannot be updated.
* @retval ::NRF_ERROR_SDM_INCORRECT_INTERRUPT_CONFIGURATION SoftDevice interrupt is already enabled, or an enabled interrupt has an illegal priority level.
* @retval ::NRF_ERROR_SDM_LFCLK_SOURCE_UNKNOWN Unknown low frequency clock source selected.
* @retval ::NRF_ERROR_INVALID_PARAM Invalid clock source configuration supplied in p_clock_lf_cfg.
*/
SVCALL(SD_SOFTDEVICE_ENABLE, uint32_t, sd_softdevice_enable(nrf_clock_lf_cfg_t const * p_clock_lf_cfg, nrf_fault_handler_t fault_handler));
/**@brief Disables the SoftDevice and by extension the protocol stack.
*
* Idempotent function to disable the SoftDevice.
*
* @post SoC library and protocol stack APIs are made unavailable.
* @post All interrupts that was protected by the SoftDevice will be disabled and initialized to priority 0 (highest).
* @post All peripherals used by the SoftDevice will be reset to default values.
* @post All of RAM become available.
* @post All interrupts are forwarded to the application.
* @post LFCLK source chosen in ::sd_softdevice_enable will be left running.
*
* @retval ::NRF_SUCCESS
*/
SVCALL(SD_SOFTDEVICE_DISABLE, uint32_t, sd_softdevice_disable(void));
/**@brief Check if the SoftDevice is enabled.
*
* @param[out] p_softdevice_enabled If the SoftDevice is enabled: 1 else 0.
*
* @retval ::NRF_SUCCESS
*/
SVCALL(SD_SOFTDEVICE_IS_ENABLED, uint32_t, sd_softdevice_is_enabled(uint8_t * p_softdevice_enabled));
/**@brief Sets the base address of the interrupt vector table for interrupts forwarded from the SoftDevice
*
* This function is only intended to be called when a bootloader is enabled.
*
* @param[in] address The base address of the interrupt vector table for forwarded interrupts.
* @retval ::NRF_SUCCESS
*/
SVCALL(SD_SOFTDEVICE_VECTOR_TABLE_BASE_SET, uint32_t, sd_softdevice_vector_table_base_set(uint32_t address));
/** @} */
#ifdef __cplusplus
}
#endif
#endif // NRF_SDM_H__
/**
@}
*/

View File

@ -0,0 +1,90 @@
/*
* 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.
*/
#ifndef NRF_SVC__
#define NRF_SVC__
#include "stdint.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef SVCALL_AS_NORMAL_FUNCTION
#define SVCALL(number, return_type, signature) return_type signature
#else
#ifndef SVCALL
#if defined (__CC_ARM)
#define SVCALL(number, return_type, signature) return_type __svc(number) signature
#elif defined (__GNUC__)
#ifdef __cplusplus
#define GCC_CAST_CPP (uint16_t)
#else
#define GCC_CAST_CPP
#endif
#define SVCALL(number, return_type, signature) \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wreturn-type\"") \
__attribute__((naked)) \
__attribute__((unused)) \
static return_type signature \
{ \
__asm( \
"svc %0\n" \
"bx r14" : : "I" (GCC_CAST_CPP number) : "r0" \
); \
} \
_Pragma("GCC diagnostic pop")
#elif defined (__ICCARM__)
#define PRAGMA(x) _Pragma(#x)
#define SVCALL(number, return_type, signature) \
PRAGMA(swi_number = (number)) \
__swi return_type signature;
#else
#define SVCALL(number, return_type, signature) return_type signature
#endif
#endif // SVCALL
#endif // SVCALL_AS_NORMAL_FUNCTION
#ifdef __cplusplus
}
#endif
#endif // NRF_SVC__

View File

@ -0,0 +1,35 @@
Copyright (c) 2007 - 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.

View File

@ -0,0 +1,447 @@
/**
* Copyright (c) 2018 - 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_atomic.h"
#ifndef NRF_ATOMIC_USE_BUILD_IN
#if (defined(__GNUC__) && defined(WIN32))
#define NRF_ATOMIC_USE_BUILD_IN 1
#else
#define NRF_ATOMIC_USE_BUILD_IN 0
#endif
#endif // NRF_ATOMIC_USE_BUILD_IN
#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U))
#define STREX_LDREX_PRESENT
#else
#include "app_util_platform.h"
#endif
#if (NRF_ATOMIC_USE_BUILD_IN == 0) && defined(STREX_LDREX_PRESENT)
#include "nrf_atomic_internal.h"
#endif
uint32_t nrf_atomic_u32_fetch_store(nrf_atomic_u32_t * p_data, uint32_t value)
{
#if NRF_ATOMIC_USE_BUILD_IN
return __atomic_exchange_n(p_data, value, __ATOMIC_SEQ_CST);
#elif defined(STREX_LDREX_PRESENT)
uint32_t old_val;
uint32_t new_val;
NRF_ATOMIC_OP(mov, old_val, new_val, p_data, value);
UNUSED_PARAMETER(old_val);
UNUSED_PARAMETER(new_val);
return old_val;
#else
CRITICAL_REGION_ENTER();
uint32_t old_val = *p_data;
*p_data = value;
CRITICAL_REGION_EXIT();
return old_val;
#endif //NRF_ATOMIC_USE_BUILD_IN
}
uint32_t nrf_atomic_u32_store(nrf_atomic_u32_t * p_data, uint32_t value)
{
#if NRF_ATOMIC_USE_BUILD_IN
__atomic_store_n(p_data, value, __ATOMIC_SEQ_CST);
return value;
#elif defined(STREX_LDREX_PRESENT)
uint32_t old_val;
uint32_t new_val;
NRF_ATOMIC_OP(mov, old_val, new_val, p_data, value);
UNUSED_PARAMETER(old_val);
UNUSED_PARAMETER(new_val);
return new_val;
#else
CRITICAL_REGION_ENTER();
*p_data = value;
CRITICAL_REGION_EXIT();
return value;
#endif //NRF_ATOMIC_USE_BUILD_IN
}
uint32_t nrf_atomic_u32_fetch_or(nrf_atomic_u32_t * p_data, uint32_t value)
{
#if NRF_ATOMIC_USE_BUILD_IN
return __atomic_fetch_or(p_data, value, __ATOMIC_SEQ_CST);
#elif defined(STREX_LDREX_PRESENT)
uint32_t old_val;
uint32_t new_val;
NRF_ATOMIC_OP(orr, old_val, new_val, p_data, value);
UNUSED_PARAMETER(old_val);
UNUSED_PARAMETER(new_val);
return old_val;
#else
CRITICAL_REGION_ENTER();
uint32_t old_val = *p_data;
*p_data |= value;
CRITICAL_REGION_EXIT();
return old_val;
#endif //NRF_ATOMIC_USE_BUILD_IN
}
uint32_t nrf_atomic_u32_or(nrf_atomic_u32_t * p_data, uint32_t value)
{
#if NRF_ATOMIC_USE_BUILD_IN
return __atomic_or_fetch(p_data, value, __ATOMIC_SEQ_CST);
#elif defined(STREX_LDREX_PRESENT)
uint32_t old_val;
uint32_t new_val;
NRF_ATOMIC_OP(orr, old_val, new_val, p_data, value);
UNUSED_PARAMETER(old_val);
UNUSED_PARAMETER(new_val);
return new_val;
#else
CRITICAL_REGION_ENTER();
*p_data |= value;
uint32_t new_value = *p_data;
CRITICAL_REGION_EXIT();
return new_value;
#endif //NRF_ATOMIC_USE_BUILD_IN
}
uint32_t nrf_atomic_u32_fetch_and(nrf_atomic_u32_t * p_data, uint32_t value)
{
#if NRF_ATOMIC_USE_BUILD_IN
return __atomic_fetch_and(p_data, value, __ATOMIC_SEQ_CST);
#elif defined(STREX_LDREX_PRESENT)
uint32_t old_val;
uint32_t new_val;
NRF_ATOMIC_OP(and, old_val, new_val, p_data, value);
UNUSED_PARAMETER(old_val);
UNUSED_PARAMETER(new_val);
return old_val;
#else
CRITICAL_REGION_ENTER();
uint32_t old_val = *p_data;
*p_data &= value;
CRITICAL_REGION_EXIT();
return old_val;
#endif //NRF_ATOMIC_USE_BUILD_IN
}
uint32_t nrf_atomic_u32_and(nrf_atomic_u32_t * p_data, uint32_t value)
{
#if NRF_ATOMIC_USE_BUILD_IN
return __atomic_and_fetch(p_data, value, __ATOMIC_SEQ_CST);
#elif defined(STREX_LDREX_PRESENT)
uint32_t old_val;
uint32_t new_val;
NRF_ATOMIC_OP(and, old_val, new_val, p_data, value);
UNUSED_PARAMETER(old_val);
UNUSED_PARAMETER(new_val);
return new_val;
#else
CRITICAL_REGION_ENTER();
*p_data &= value;
uint32_t new_value = *p_data;
CRITICAL_REGION_EXIT();
return new_value;
#endif //NRF_ATOMIC_USE_BUILD_IN
}
uint32_t nrf_atomic_u32_fetch_xor(nrf_atomic_u32_t * p_data, uint32_t value)
{
#if NRF_ATOMIC_USE_BUILD_IN
return __atomic_fetch_xor(p_data, value, __ATOMIC_SEQ_CST);
#elif defined(STREX_LDREX_PRESENT)
uint32_t old_val;
uint32_t new_val;
NRF_ATOMIC_OP(eor, old_val, new_val, p_data, value);
UNUSED_PARAMETER(old_val);
UNUSED_PARAMETER(new_val);
return old_val;
#else
CRITICAL_REGION_ENTER();
uint32_t old_val = *p_data;
*p_data ^= value;
CRITICAL_REGION_EXIT();
return old_val;
#endif //NRF_ATOMIC_USE_BUILD_IN
}
uint32_t nrf_atomic_u32_xor(nrf_atomic_u32_t * p_data, uint32_t value)
{
#if NRF_ATOMIC_USE_BUILD_IN
return __atomic_xor_fetch(p_data, value, __ATOMIC_SEQ_CST);
#elif defined(STREX_LDREX_PRESENT)
uint32_t old_val;
uint32_t new_val;
NRF_ATOMIC_OP(eor, old_val, new_val, p_data, value);
UNUSED_PARAMETER(old_val);
UNUSED_PARAMETER(new_val);
return new_val;
#else
CRITICAL_REGION_ENTER();
*p_data ^= value;
uint32_t new_value = *p_data;
CRITICAL_REGION_EXIT();
return new_value;
#endif //NRF_ATOMIC_USE_BUILD_IN
}
uint32_t nrf_atomic_u32_fetch_add(nrf_atomic_u32_t * p_data, uint32_t value)
{
#if NRF_ATOMIC_USE_BUILD_IN
return __atomic_fetch_add(p_data, value, __ATOMIC_SEQ_CST);
#elif defined(STREX_LDREX_PRESENT)
uint32_t old_val;
uint32_t new_val;
NRF_ATOMIC_OP(add, old_val, new_val, p_data, value);
UNUSED_PARAMETER(old_val);
UNUSED_PARAMETER(new_val);
return old_val;
#else
CRITICAL_REGION_ENTER();
uint32_t old_val = *p_data;
*p_data += value;
CRITICAL_REGION_EXIT();
return old_val;
#endif //NRF_ATOMIC_USE_BUILD_IN
}
uint32_t nrf_atomic_u32_add(nrf_atomic_u32_t * p_data, uint32_t value)
{
#if NRF_ATOMIC_USE_BUILD_IN
return __atomic_add_fetch(p_data, value, __ATOMIC_SEQ_CST);
#elif defined(STREX_LDREX_PRESENT)
uint32_t old_val;
uint32_t new_val;
NRF_ATOMIC_OP(add, old_val, new_val, p_data, value);
UNUSED_PARAMETER(old_val);
UNUSED_PARAMETER(new_val);
return new_val;
#else
CRITICAL_REGION_ENTER();
*p_data += value;
uint32_t new_value = *p_data;
CRITICAL_REGION_EXIT();
return new_value;
#endif //NRF_ATOMIC_USE_BUILD_IN
}
uint32_t nrf_atomic_u32_fetch_sub(nrf_atomic_u32_t * p_data, uint32_t value)
{
#if NRF_ATOMIC_USE_BUILD_IN
return __atomic_fetch_sub(p_data, value, __ATOMIC_SEQ_CST);
#elif defined(STREX_LDREX_PRESENT)
uint32_t old_val;
uint32_t new_val;
NRF_ATOMIC_OP(sub, old_val, new_val, p_data, value);
UNUSED_PARAMETER(old_val);
UNUSED_PARAMETER(new_val);
return old_val;
#else
CRITICAL_REGION_ENTER();
uint32_t old_val = *p_data;
*p_data -= value;
CRITICAL_REGION_EXIT();
return old_val;
#endif //NRF_ATOMIC_USE_BUILD_IN
}
uint32_t nrf_atomic_u32_sub(nrf_atomic_u32_t * p_data, uint32_t value)
{
#if NRF_ATOMIC_USE_BUILD_IN
return __atomic_sub_fetch(p_data, value, __ATOMIC_SEQ_CST);
#elif defined(STREX_LDREX_PRESENT)
uint32_t old_val;
uint32_t new_val;
NRF_ATOMIC_OP(sub, old_val, new_val, p_data, value);
UNUSED_PARAMETER(old_val);
UNUSED_PARAMETER(new_val);
return new_val;
#else
CRITICAL_REGION_ENTER();
*p_data -= value;
uint32_t new_value = *p_data;
CRITICAL_REGION_EXIT();
return new_value;
#endif //NRF_ATOMIC_USE_BUILD_IN
}
bool nrf_atomic_u32_cmp_exch(nrf_atomic_u32_t * p_data,
uint32_t * p_expected,
uint32_t desired)
{
#if NRF_ATOMIC_USE_BUILD_IN
return __atomic_compare_exchange(p_data,
p_expected,
&desired,
1,
__ATOMIC_SEQ_CST,
__ATOMIC_SEQ_CST);
#elif defined(STREX_LDREX_PRESENT)
return nrf_atomic_internal_cmp_exch(p_data, p_expected, desired);
#else
CRITICAL_REGION_ENTER();
if(*p_data == *p_expected)
{
*p_data = desired;
return true;
}
else
{
*p_expected = *p_data;
return false;
}
CRITICAL_REGION_EXIT();
#endif
}
uint32_t nrf_atomic_u32_fetch_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value)
{
#if NRF_ATOMIC_USE_BUILD_IN
uint32_t expected = *p_data;
uint32_t new_val;
bool success;
do
{
if (expected >= value)
{
new_val = expected - value;
}
else
{
new_val = expected;
}
success = __atomic_compare_exchange(p_data,
&expected,
&new_val,
1,
__ATOMIC_SEQ_CST,
__ATOMIC_SEQ_CST);
} while(!success);
return expected;
#elif defined(STREX_LDREX_PRESENT)
uint32_t old_val;
uint32_t new_val;
NRF_ATOMIC_OP(sub_hs, old_val, new_val, p_data, value);
UNUSED_PARAMETER(old_val);
UNUSED_PARAMETER(new_val);
return old_val;
#else
CRITICAL_REGION_ENTER();
uint32_t old_val = *p_data;
*p_data -= value;
CRITICAL_REGION_EXIT();
return old_val;
#endif //NRF_ATOMIC_USE_BUILD_IN
}
uint32_t nrf_atomic_u32_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value)
{
#if NRF_ATOMIC_USE_BUILD_IN
uint32_t expected = *p_data;
uint32_t new_val;
bool success;
do
{
if (expected >= value)
{
new_val = expected - value;
}
else
{
new_val = expected;
}
success = __atomic_compare_exchange(p_data,
&expected,
&new_val,
1,
__ATOMIC_SEQ_CST,
__ATOMIC_SEQ_CST);
} while(!success);
return new_val;
#elif defined(STREX_LDREX_PRESENT)
uint32_t old_val;
uint32_t new_val;
NRF_ATOMIC_OP(sub_hs, old_val, new_val, p_data, value);
UNUSED_PARAMETER(old_val);
UNUSED_PARAMETER(new_val);
return new_val;
#else
CRITICAL_REGION_ENTER();
*p_data -= value;
uint32_t new_value = *p_data;
CRITICAL_REGION_EXIT();
return new_value;
#endif //NRF_ATOMIC_USE_BUILD_IN
}
uint32_t nrf_atomic_flag_set_fetch(nrf_atomic_flag_t * p_data)
{
return nrf_atomic_u32_fetch_or(p_data, 1);
}
uint32_t nrf_atomic_flag_set(nrf_atomic_flag_t * p_data)
{
return nrf_atomic_u32_or(p_data, 1);
}
uint32_t nrf_atomic_flag_clear_fetch(nrf_atomic_flag_t * p_data)
{
return nrf_atomic_u32_fetch_and(p_data, 0);
}
uint32_t nrf_atomic_flag_clear(nrf_atomic_flag_t * p_data)
{
return nrf_atomic_u32_and(p_data, 0);
}

View File

@ -0,0 +1,274 @@
/**
* 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_atomic Atomic operations API
* @ingroup app_common
* @{
*
* @brief @tagAPI52 This module implements C11 stdatomic.h simplified API.
At this point only Cortex-M3/M4 cores are supported (LDREX/STREX instructions).
* Atomic types are limited to @ref nrf_atomic_u32_t and @ref nrf_atomic_flag_t.
*/
#ifndef NRF_ATOMIC_H__
#define NRF_ATOMIC_H__
#include "sdk_common.h"
/**
* @brief Atomic 32 bit unsigned type
* */
typedef volatile uint32_t nrf_atomic_u32_t;
/**
* @brief Atomic 1 bit flag type (technically 32 bit)
* */
typedef volatile uint32_t nrf_atomic_flag_t;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Stores value to an atomic object
*
* @param[in] p_data Atomic memory pointer
* @param[in] value Value to store
*
* @return Old value stored into atomic object
* */
uint32_t nrf_atomic_u32_fetch_store(nrf_atomic_u32_t * p_data, uint32_t value);
/**
* @brief Stores value to an atomic object
*
* @param[in] p_data Atomic memory pointer
* @param[in] value Value to store
*
* @return New value stored into atomic object
* */
uint32_t nrf_atomic_u32_store(nrf_atomic_u32_t * p_data, uint32_t value);
/**
* @brief Logical OR operation on an atomic object
*
* @param[in] p_data Atomic memory pointer
* @param[in] value Value of second operand OR operation
*
* @return Old value stored into atomic object
* */
uint32_t nrf_atomic_u32_fetch_or(nrf_atomic_u32_t * p_data, uint32_t value);
/**
* @brief Logical OR operation on an atomic object
*
* @param[in] p_data Atomic memory pointer
* @param[in] value Value of second operand OR operation
*
* @return New value stored into atomic object
* */
uint32_t nrf_atomic_u32_or(nrf_atomic_u32_t * p_data, uint32_t value);
/**
* @brief Logical AND operation on an atomic object
*
* @param[in] p_data Atomic memory pointer
* @param[in] value Value of second operand AND operation
*
* @return Old value stored into atomic object
* */
uint32_t nrf_atomic_u32_fetch_and(nrf_atomic_u32_t * p_data, uint32_t value);
/**
* @brief Logical AND operation on an atomic object
*
* @param[in] p_data Atomic memory pointer
* @param[in] value Value of second operand AND operation
*
* @return New value stored into atomic object
* */
uint32_t nrf_atomic_u32_and(nrf_atomic_u32_t * p_data, uint32_t value);
/**
* @brief Logical XOR operation on an atomic object
*
* @param[in] p_data Atomic memory pointer
* @param[in] value Value of second operand XOR operation
*
* @return Old value stored into atomic object
* */
uint32_t nrf_atomic_u32_fetch_xor(nrf_atomic_u32_t * p_data, uint32_t value);
/**
* @brief Logical XOR operation on an atomic object
*
* @param[in] p_data Atomic memory pointer
* @param[in] value Value of second operand XOR operation
*
* @return New value stored into atomic object
* */
uint32_t nrf_atomic_u32_xor(nrf_atomic_u32_t * p_data, uint32_t value);
/**
* @brief Arithmetic ADD operation on an atomic object
*
* @param[in] p_data Atomic memory pointer
* @param[in] value Value of second operand ADD operation
*
* @return Old value stored into atomic object
* */
uint32_t nrf_atomic_u32_fetch_add(nrf_atomic_u32_t * p_data, uint32_t value);
/**
* @brief Arithmetic ADD operation on an atomic object
*
* @param[in] p_data Atomic memory pointer
* @param[in] value Value of second operand ADD operation
*
* @return New value stored into atomic object
* */
uint32_t nrf_atomic_u32_add(nrf_atomic_u32_t * p_data, uint32_t value);
/**
* @brief Arithmetic SUB operation on an atomic object
*
* @param[in] p_data Atomic memory pointer
* @param[in] value Value of second operand SUB operation
*
* @return Old value stored into atomic object
* */
uint32_t nrf_atomic_u32_fetch_sub(nrf_atomic_u32_t * p_data, uint32_t value);
/**
* @brief Arithmetic SUB operation on an atomic object
*
* @param[in] p_data Atomic memory pointer
* @param[in] value Value of second operand SUB operation
*
* @return New value stored into atomic object
* */
uint32_t nrf_atomic_u32_sub(nrf_atomic_u32_t * p_data, uint32_t value);
/**
* @brief If value at pointer is equal to expected value, changes value at pointer to desired
*
* Atomically compares the value pointed to by p_data with the value pointed to by p_expected,
* and if those are equal, replaces the former with desired. Otherwise, loads the actual value
* pointed to by p_data into *p_expected.
*
* @param p_data Atomic memory pointer to test and modify.
* @param p_expected Pointer to test value.
* @param desired Value to be stored to atomic memory.
*
* @retval true *p_data was equal to *p_expected
* @retval false *p_data was not equal to *p_expected
*/
bool nrf_atomic_u32_cmp_exch(nrf_atomic_u32_t * p_data,
uint32_t * p_expected,
uint32_t desired);
/**
* @brief Arithmetic SUB operation on an atomic object performed if object >= value.
*
* @param[in] p_data Atomic memory pointer
* @param[in] value Value of second operand SUB operation
*
* @return Old value stored into atomic object
* */
uint32_t nrf_atomic_u32_fetch_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value);
/**
* @brief Arithmetic SUB operation on an atomic object performed if object >= value.
*
* @param[in] p_data Atomic memory pointer
* @param[in] value Value of second operand SUB operation
*
* @return New value stored into atomic object
* */
uint32_t nrf_atomic_u32_sub_hs(nrf_atomic_u32_t * p_data, uint32_t value);
/**************************************************************************************************/
/**
* @brief Logic one bit flag set operation on an atomic object
*
* @param[in] p_data Atomic flag memory pointer
*
* @return Old flag value
* */
uint32_t nrf_atomic_flag_set_fetch(nrf_atomic_flag_t * p_data);
/**
* @brief Logic one bit flag set operation on an atomic object
*
* @param[in] p_data Atomic flag memory pointer
*
* @return New flag value
* */
uint32_t nrf_atomic_flag_set(nrf_atomic_flag_t * p_data);
/**
* @brief Logic one bit flag clear operation on an atomic object
*
* @param[in] p_data Atomic flag memory pointer
*
* @return Old flag value
* */
uint32_t nrf_atomic_flag_clear_fetch(nrf_atomic_flag_t * p_data);
/**
* @brief Logic one bit flag clear operation on an atomic object
*
* @param[in] p_data Atomic flag memory pointer
*
* @return New flag value
* */
uint32_t nrf_atomic_flag_clear(nrf_atomic_flag_t * p_data);
#ifdef __cplusplus
}
#endif
#endif /* NRF_ATOMIC_H__ */
/** @} */

View File

@ -0,0 +1,343 @@
/**
* 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.
*
*/
#ifndef NRF_ATOMIC_INTERNAL_H__
#define NRF_ATOMIC_INTERNAL_H__
#include "sdk_common.h"
#include <stdbool.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
*
* @defgroup nrf_atomic_internal Atomic operations internals
* @ingroup nrf_atomic
* @{
*
*/
/* Only Cortex M cores > 3 support LDREX/STREX instructions*/
#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) == 0
#error "Unsupported core version"
#endif
#if defined ( __CC_ARM )
static __asm uint32_t nrf_atomic_internal_mov(nrf_atomic_u32_t * p_ptr,
uint32_t value,
uint32_t * p_new)
{
/* The base standard provides for passing arguments in core registers (r0-r3) and on the stack.
* Registers r4 and r5 have to be saved on stack. Note that only even number of register push are
* allowed. This is a requirement of the Procedure Call Standard for the ARM Architecture [AAPCS].
* */
push {r4, r5}
mov r4, r0
loop_mov
ldrex r0, [r4]
mov r5, r1
strex r3, r5, [r4]
cmp r3, #0
bne loop_mov
str r5, [r2]
pop {r4, r5}
bx lr
}
static __asm uint32_t nrf_atomic_internal_orr(nrf_atomic_u32_t * p_ptr,
uint32_t value,
uint32_t * p_new)
{
push {r4, r5}
mov r4, r0
loop_orr
ldrex r0, [r4]
orr r5, r0, r1
strex r3, r5, [r4]
cmp r3, #0
bne loop_orr
str r5, [r2]
pop {r4, r5}
bx lr
}
static __asm uint32_t nrf_atomic_internal_and(nrf_atomic_u32_t * p_ptr,
uint32_t value,
uint32_t * p_new)
{
push {r4, r5}
mov r4, r0
loop_and
ldrex r0, [r4]
and r5, r0, r1
strex r3, r5, [r4]
cmp r3, #0
bne loop_and
str r5, [r2]
pop {r4, r5}
bx lr
}
static __asm uint32_t nrf_atomic_internal_eor(nrf_atomic_u32_t * p_ptr,
uint32_t value,
uint32_t * p_new)
{
push {r4, r5}
mov r4, r0
loop_eor
ldrex r0, [r4]
eor r5, r0, r1
strex r3, r5, [r4]
cmp r3, #0
bne loop_eor
str r5, [r2]
pop {r4, r5}
bx lr
}
static __asm uint32_t nrf_atomic_internal_add(nrf_atomic_u32_t * p_ptr,
uint32_t value,
uint32_t * p_new)
{
push {r4, r5}
mov r4, r0
loop_add
ldrex r0, [r4]
add r5, r0, r1
strex r3, r5, [r4]
cmp r3, #0
bne loop_add
str r5, [r2]
pop {r4, r5}
bx lr
}
static __asm uint32_t nrf_atomic_internal_sub(nrf_atomic_u32_t * p_ptr,
uint32_t value,
uint32_t * p_new)
{
push {r4, r5}
mov r4, r0
loop_sub
ldrex r0, [r4]
sub r5, r0, r1
strex r3, r5, [r4]
cmp r3, #0
bne loop_sub
str r5, [r2]
pop {r4, r5}
bx lr
}
static __asm bool nrf_atomic_internal_cmp_exch(nrf_atomic_u32_t * p_data,
uint32_t * p_expected,
uint32_t value)
{
#define RET_REG r0
#define P_EXPC r1
#define VALUE r2
#define STR_RES r3
#define P_DATA r4
#define EXPC_VAL r5
#define ACT_VAL r6
push {r4-r6}
mov P_DATA, r0
mov RET_REG, #0
loop_cmp_exch
ldrex ACT_VAL, [P_DATA]
ldr EXPC_VAL, [P_EXPC]
cmp ACT_VAL, EXPC_VAL
ittee eq
strexeq STR_RES, VALUE, [P_DATA]
moveq RET_REG, #1
strexne STR_RES, ACT_VAL, [P_DATA]
strne ACT_VAL, [P_EXPC]
cmp STR_RES, #0
itt ne
movne RET_REG, #0
bne loop_cmp_exch
pop {r4-r6}
bx lr
#undef RET_REG
#undef P_EXPC
#undef VALUE
#undef STR_RES
#undef P_DATA
#undef EXPC_VAL
#undef ACT_VAL
}
static __asm uint32_t nrf_atomic_internal_sub_hs(nrf_atomic_u32_t * p_ptr,
uint32_t value,
uint32_t * p_new)
{
push {r4, r5}
mov r4, r0
loop_sub_ge
ldrex r0, [r4]
cmp r0, r1
ite hs
subhs r5, r0, r1
movlo r5, r0
strex r3, r5, [r4]
cmp r3, #0
bne loop_sub_ge
str r5, [r2]
pop {r4, r5}
bx lr
}
#define NRF_ATOMIC_OP(asm_op, old_val, new_val, ptr, value) \
old_val = nrf_atomic_internal_##asm_op(ptr, value, &new_val)
#elif defined ( __ICCARM__ ) || defined ( __GNUC__ )
/**
* @brief Atomic operation generic macro
* @param[in] asm_op operation: mov, orr, and, eor, add, sub
* @param[out] old_val atomic object output (uint32_t), value before operation
* @param[out] new_val atomic object output (uint32_t), value after operation
* @param[in] value atomic operation operand
* */
#define NRF_ATOMIC_OP(asm_op, old_val, new_val, ptr, value) \
{ \
uint32_t str_res; \
__ASM volatile( \
"1: ldrex %["#old_val"], [%["#ptr"]]\n" \
NRF_ATOMIC_OP_##asm_op(new_val, old_val, value) \
" strex %[str_res], %["#new_val"], [%["#ptr"]]\n" \
" teq %[str_res], #0\n" \
" bne.n 1b" \
: \
[old_val]"=&r" (old_val), \
[new_val]"=&r" (new_val), \
[str_res]"=&r" (str_res) \
: \
[ptr]"r" (ptr), \
[value]"r" (value) \
: "cc"); \
UNUSED_PARAMETER(str_res); \
}
#define NRF_ATOMIC_OP_mov(new_val, old_val, value) "mov %["#new_val"], %["#value"]\n"
#define NRF_ATOMIC_OP_orr(new_val, old_val, value) "orr %["#new_val"], %["#old_val"], %["#value"]\n"
#define NRF_ATOMIC_OP_and(new_val, old_val, value) "and %["#new_val"], %["#old_val"], %["#value"]\n"
#define NRF_ATOMIC_OP_eor(new_val, old_val, value) "eor %["#new_val"], %["#old_val"], %["#value"]\n"
#define NRF_ATOMIC_OP_add(new_val, old_val, value) "add %["#new_val"], %["#old_val"], %["#value"]\n"
#define NRF_ATOMIC_OP_sub(new_val, old_val, value) "sub %["#new_val"], %["#old_val"], %["#value"]\n"
#define NRF_ATOMIC_OP_sub_hs(new_val, old_val, value) \
"cmp %["#old_val"], %["#value"]\n " \
"ite hs\n" \
"subhs %["#new_val"], %["#old_val"], %["#value"]\n" \
"movlo %["#new_val"], %["#old_val"]\n"
static inline bool nrf_atomic_internal_cmp_exch(nrf_atomic_u32_t * p_data,
uint32_t * p_expected,
uint32_t value)
{
bool res = false;
uint32_t str_res = 0;
uint32_t act_val = 0;
uint32_t exp_val = 0;
UNUSED_VARIABLE(str_res);
UNUSED_VARIABLE(act_val);
UNUSED_VARIABLE(exp_val);
__ASM volatile(
"1: ldrex %[act_val], [%[ptr]]\n"
" ldr %[exp_val], [%[expc]]\n"
" cmp %[act_val], %[exp_val]\n"
" ittee eq\n"
" strexeq %[str_res], %[value], [%[ptr]]\n"
" moveq %[res], #1\n"
" strexne %[str_res], %[act_val], [%[ptr]]\n"
" strne %[act_val], [%[expc]]\n"
" cmp %[str_res], #0\n"
" itt ne\n"
" movne %[res], #0\n"
" bne.n 1b"
:
[res] "=&r" (res),
[exp_val] "=&r" (exp_val),
[act_val] "=&r" (act_val),
[str_res] "=&r" (str_res)
:
"0" (res),
"1" (exp_val),
"2" (act_val),
[expc] "r" (p_expected),
[ptr] "r" (p_data),
[value] "r" (value)
: "cc");
return res;
}
#else
#error "Unsupported compiler"
#endif
#ifdef __cplusplus
}
#endif
#endif /* NRF_ATOMIC_INTERNAL_H__ */
/** @} */

View File

@ -0,0 +1,153 @@
/**
* 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.
*
*/
#ifndef NRF_ATOMIC_SANITY_CHECK_H__
#define NRF_ATOMIC_SANITY_CHECK_H__
#include "nrf_atomic.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Quick sanity check of nrf_atomic API
* */
static inline void nrf_atomic_sanity_check(void)
{
#if defined(DEBUG_NRF) || defined(DEBUG_NRF_USER)
nrf_atomic_u32_t val;
nrf_atomic_u32_t flag;
/*Fetch version tests*/
val = 0;
ASSERT(nrf_atomic_u32_store_fetch(&val, 10) == 0);
ASSERT(nrf_atomic_u32_store_fetch(&val, 0) == 10);
val = 0;
ASSERT(nrf_atomic_u32_or_fetch(&val, 1 << 16) == 0);
ASSERT(nrf_atomic_u32_or_fetch(&val, 1 << 5) == ((1 << 16)));
ASSERT(nrf_atomic_u32_or_fetch(&val, 1 << 5) == ((1 << 16) | (1 << 5)));
ASSERT(nrf_atomic_u32_or_fetch(&val, 0) == ((1 << 16) | (1 << 5)));
ASSERT(nrf_atomic_u32_or_fetch(&val, 0xFFFFFFFF) == ((1 << 16) | (1 << 5)));
ASSERT(nrf_atomic_u32_or_fetch(&val, 0xFFFFFFFF) == (0xFFFFFFFF));
val = 0xFFFFFFFF;
ASSERT(nrf_atomic_u32_and_fetch(&val, ~(1 << 16)) == 0xFFFFFFFF);
ASSERT(nrf_atomic_u32_and_fetch(&val, ~(1 << 5)) == (0xFFFFFFFF & ~((1 << 16))));
ASSERT(nrf_atomic_u32_and_fetch(&val, 0) == (0xFFFFFFFF & ~(((1 << 16) | (1 << 5)))));
ASSERT(nrf_atomic_u32_and_fetch(&val, 0xFFFFFFFF) == (0));
val = 0;
ASSERT(nrf_atomic_u32_xor_fetch(&val, (1 << 16)) == 0);
ASSERT(nrf_atomic_u32_xor_fetch(&val, (1 << 5)) == ((1 << 16)));
ASSERT(nrf_atomic_u32_xor_fetch(&val, 0) == ((1 << 16) | (1 << 5)));
ASSERT(nrf_atomic_u32_xor_fetch(&val, (1 << 16) | (1 << 5)) == ((1 << 16) | (1 << 5)));
ASSERT(nrf_atomic_u32_xor_fetch(&val, 0) == (0));
val = 0;
ASSERT(nrf_atomic_u32_add_fetch(&val, 100) == 0);
ASSERT(nrf_atomic_u32_add_fetch(&val, 100) == 100);
ASSERT(nrf_atomic_u32_add_fetch(&val, 1 << 24) == 200);
ASSERT(nrf_atomic_u32_add_fetch(&val, 0) == (200 + (1 << 24)));
ASSERT(nrf_atomic_u32_add_fetch(&val, 0xFFFFFFFF) == (200 + (1 << 24)));
ASSERT(nrf_atomic_u32_add_fetch(&val, 0) == (200 - 1 + (1 << 24)));
val = 1000;
ASSERT(nrf_atomic_u32_sub_fetch(&val, 100) == 1000);
ASSERT(nrf_atomic_u32_sub_fetch(&val, 100) == 900);
ASSERT(nrf_atomic_u32_sub_fetch(&val, 0) == 800);
ASSERT(nrf_atomic_u32_sub_fetch(&val, 0xFFFFFFFF) == 800);
ASSERT(nrf_atomic_u32_sub_fetch(&val, 0) == 801);
flag = 0;
ASSERT(nrf_atomic_flag_set_fetch(&flag) == 0);
ASSERT(nrf_atomic_flag_set_fetch(&flag) == 1);
ASSERT(nrf_atomic_flag_clear_fetch(&flag) == 1);
ASSERT(nrf_atomic_flag_clear_fetch(&flag) == 0);
/*No fetch version tests*/
val = 0;
ASSERT(nrf_atomic_u32_store(&val, 10) == 10);
ASSERT(nrf_atomic_u32_store(&val, 0) == 0);
val = 0;
ASSERT(nrf_atomic_u32_or(&val, 1 << 16) == 1 << 16);
ASSERT(nrf_atomic_u32_or(&val, 1 << 5) == ((1 << 16) | (1 << 5)));
ASSERT(nrf_atomic_u32_or(&val, 1 << 5) == ((1 << 16) | (1 << 5)));
ASSERT(nrf_atomic_u32_or(&val, 0) == ((1 << 16) | (1 << 5)));
ASSERT(nrf_atomic_u32_or(&val, 0xFFFFFFFF) == 0xFFFFFFFF);
val = 0xFFFFFFFF;
ASSERT(nrf_atomic_u32_and(&val, ~(1 << 16)) == (0xFFFFFFFF & ~((1 << 16))));
ASSERT(nrf_atomic_u32_and(&val, ~(1 << 5)) == (0xFFFFFFFF & ~(((1 << 16) | (1 << 5)))));
ASSERT(nrf_atomic_u32_and(&val, 0) == 0);
val = 0;
ASSERT(nrf_atomic_u32_xor(&val, (1 << 16)) == ((1 << 16)));
ASSERT(nrf_atomic_u32_xor(&val, (1 << 5)) == ((1 << 16) | (1 << 5)));
ASSERT(nrf_atomic_u32_xor(&val, 0) == ((1 << 16) | (1 << 5)));
ASSERT(nrf_atomic_u32_xor(&val, (1 << 16) | (1 << 5)) == 0);
val = 0;
ASSERT(nrf_atomic_u32_add(&val, 100) == 100);
ASSERT(nrf_atomic_u32_add(&val, 100) == 200);
ASSERT(nrf_atomic_u32_add(&val, 1 << 24) == (200 + (1 << 24)));
ASSERT(nrf_atomic_u32_add(&val, 0) == (200 + (1 << 24)));
ASSERT(nrf_atomic_u32_add(&val, 0xFFFFFFFF) == (200 - 1 + (1 << 24)));
val = 1000;
ASSERT(nrf_atomic_u32_sub(&val, 100) == 900);
ASSERT(nrf_atomic_u32_sub(&val, 100) == 800);
ASSERT(nrf_atomic_u32_sub(&val, 0) == 800);
ASSERT(nrf_atomic_u32_sub(&val, 0xFFFFFFFF) == 801);
flag = 0;
ASSERT(nrf_atomic_flag_set(&flag) == 1);
ASSERT(nrf_atomic_flag_set(&flag) == 1);
ASSERT(nrf_atomic_flag_clear(&flag) == 0);
ASSERT(nrf_atomic_flag_clear(&flag) == 0);
#endif
}
#ifdef __cplusplus
}
#endif
#endif /* NRF_ATOMIC_SANITY_CHECK_H__ */

View File

@ -0,0 +1,189 @@
/**
* Copyright (c) 2011 - 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 <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "app_util.h"
#include "nrf_atfifo.h"
#include "nrf_atfifo_internal.h"
#if NRF_ATFIFO_CONFIG_LOG_ENABLED
#define NRF_LOG_LEVEL NRF_ATFIFO_CONFIG_LOG_LEVEL
#define NRF_LOG_INIT_FILTER_LEVEL NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL
#define NRF_LOG_INFO_COLOR NRF_ATFIFO_CONFIG_INFO_COLOR
#define NRF_LOG_DEBUG_COLOR NRF_ATFIFO_CONFIG_DEBUG_COLOR
#else
#define NRF_LOG_LEVEL 0
#endif // NRF_ATFIFO_CONFIG_LOG_ENABLED
#include "nrf_log.h"
/* Unions testing */
STATIC_ASSERT(sizeof(nrf_atfifo_postag_t) == sizeof(uint32_t));
ret_code_t nrf_atfifo_init(nrf_atfifo_t * const p_fifo, void * p_buf, uint16_t buf_size, uint16_t item_size)
{
if (NULL == p_buf)
{
NRF_LOG_INST_ERROR(p_fifo->p_log, "Initialization failed. p_buf == NULL");
return NRF_ERROR_NULL;
}
if (0 != (buf_size % item_size))
{
NRF_LOG_INST_ERROR(p_fifo->p_log, "Initialization failed. Buf_size not multiple of item_size");
return NRF_ERROR_INVALID_LENGTH;
}
p_fifo->p_buf = p_buf;
p_fifo->tail.tag = 0;
p_fifo->head.tag = 0;
p_fifo->buf_size = buf_size;
p_fifo->item_size = item_size;
NRF_LOG_INST_INFO(p_fifo->p_log, "Initialized.");
return NRF_SUCCESS;
}
ret_code_t nrf_atfifo_clear(nrf_atfifo_t * const p_fifo)
{
bool released = nrf_atfifo_space_clear(p_fifo);
NRF_LOG_INST_INFO(p_fifo->p_log, "Cleared result:%s", released ? "success" : "busy");
return released ? NRF_SUCCESS : NRF_ERROR_BUSY;
}
ret_code_t nrf_atfifo_alloc_put(nrf_atfifo_t * const p_fifo, void const * p_var, size_t size, bool * const p_visible)
{
nrf_atfifo_item_put_t context;
bool visible;
void * p_data = nrf_atfifo_item_alloc(p_fifo, &context);
if (NULL == p_data)
{
NRF_LOG_INST_WARNING(p_fifo->p_log, "Copying in element (0x%08X) failed - no space.", p_var);
return NRF_ERROR_NO_MEM;
}
memcpy(p_data, p_var, size);
visible = nrf_atfifo_item_put(p_fifo, &context);
if (NULL != p_visible)
{
*p_visible = visible;
}
NRF_LOG_INST_DEBUG(p_fifo->p_log, "Element (0x%08X) copied in.", p_var);
return NRF_SUCCESS;
}
void * nrf_atfifo_item_alloc(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context)
{
if (nrf_atfifo_wspace_req(p_fifo, &(p_context->last_tail)))
{
void * p_item = ((uint8_t*)(p_fifo->p_buf)) + p_context->last_tail.pos.wr;
NRF_LOG_INST_DEBUG(p_fifo->p_log, "Allocated element (0x%08X).", p_item);
return p_item;
}
NRF_LOG_INST_WARNING(p_fifo->p_log, "Allocation failed - no space.");
return NULL;
}
bool nrf_atfifo_item_put(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context)
{
if ((p_context->last_tail.pos.wr) == (p_context->last_tail.pos.rd))
{
NRF_LOG_INST_DEBUG(p_fifo->p_log, "Put (uninterrupted)");
nrf_atfifo_wspace_close(p_fifo);
return true;
}
NRF_LOG_INST_DEBUG(p_fifo->p_log, "Put (interrupted!)");
return false;
}
ret_code_t nrf_atfifo_get_free(nrf_atfifo_t * const p_fifo, void * const p_var, size_t size, bool * p_released)
{
nrf_atfifo_item_get_t context;
bool released;
void const * p_s = nrf_atfifo_item_get(p_fifo, &context);
if (NULL == p_s)
{
NRF_LOG_INST_WARNING(p_fifo->p_log, "Copying out failed - no item in the FIFO.");
return NRF_ERROR_NOT_FOUND;
}
memcpy(p_var, p_s, size);
released = nrf_atfifo_item_free(p_fifo, &context);
if (NULL != p_released)
{
*p_released = released;
}
NRF_LOG_INST_DEBUG(p_fifo->p_log, "Element (0x%08X) copied out.", p_var);
return NRF_SUCCESS;
}
void * nrf_atfifo_item_get(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context)
{
if (nrf_atfifo_rspace_req(p_fifo, &(p_context->last_head)))
{
void * p_item = ((uint8_t*)(p_fifo->p_buf)) + p_context->last_head.pos.rd;
NRF_LOG_INST_DEBUG(p_fifo->p_log, "Get element: 0x%08X", p_item);
return p_item;
}
NRF_LOG_INST_WARNING(p_fifo->p_log, "Get failed - no item in the FIFO.");
return NULL;
}
bool nrf_atfifo_item_free(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context)
{
if ((p_context->last_head.pos.wr) == (p_context->last_head.pos.rd))
{
NRF_LOG_INST_DEBUG(p_fifo->p_log, "Free (uninterrupted)");
nrf_atfifo_rspace_close(p_fifo);
return true;
}
NRF_LOG_INST_DEBUG(p_fifo->p_log, "Free (interrupted)");
return false;
}

View File

@ -0,0 +1,424 @@
/**
* Copyright (c) 2011 - 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 NRF_ATFIFO_H__
#define NRF_ATFIFO_H__
#include <stdint.h>
#include <stdbool.h>
#include "sdk_config.h"
#include "nordic_common.h"
#include "nrf_assert.h"
#include "sdk_errors.h"
#include "nrf_log_instance.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup nrf_atfifo Atomic FIFO
* @ingroup app_common
*
* @brief @tagAPI52 FIFO implementation that allows for making atomic transactions without
* locking interrupts.
*
* @details There are two types of functions to prepare the FIFO writing:
* - Single function for simple access:
* @code
* if (NRF_SUCCESS != nrf_atfifo_simple_put(my_fifo, &data, NULL))
* {
* // Error handling
* }
* @endcode
* - Function pair to limit data copying:
* @code
* struct point3d
* {
* int x, y, z;
* }point3d_t;
* nrf_atfifo_context_t context;
* point3d_t * point;
*
* if (NULL != (point = nrf_atfifo_item_alloc(my_fifo, &context)))
* {
* point->x = a;
* point->y = b;
* point->z = c;
* if (nrf_atfifo_item_put(my_fifo, &context))
* {
* // Send information to the rest of the system
* // that there is new data in the FIFO available for reading.
* }
* }
* else
* {
* // Error handling
* }
*
* @endcode
* @note
* This atomic FIFO implementation requires that the operation that is
* opened last is finished (committed/flushed) first.
* This is typical for operations performed from the interrupt runtime
* when the other operation is performed from the main thread.
*
* This implementation does not support typical multithreading operating system
* access where operations can be started and finished in totally unrelated order.
*
* @{
*/
/**
* @brief Read and write position structure.
*
* A structure that holds the read and write position used by the FIFO head and tail.
*/
typedef struct nrf_atfifo_postag_pos_s
{
uint16_t wr; //!< First free space to write the data
uint16_t rd; //!< A place after the last data to read
}nrf_atfifo_postag_pos_t;
/**
* @brief End data index tag.
*
* A tag used to mark the end of data.
* To properly realize atomic data committing, the whole variable has to be
* accessed atomically.
*/
typedef union nrf_atfifo_postag_u
{
uint32_t tag; //!< Whole tag, used for atomic, 32-bit access
nrf_atfifo_postag_pos_t pos; //!< Structure that holds reading and writing position separately
}nrf_atfifo_postag_t;
/**
* @brief The FIFO instance.
*
* The instance of atomic FIFO.
* Used with all FIFO functions.
*/
typedef struct nrf_atfifo_s
{
void * p_buf; //!< Pointer to the data buffer
nrf_atfifo_postag_t tail; //!< Read and write tail position tag
nrf_atfifo_postag_t head; //!< Read and write head position tag
uint16_t buf_size; //!< FIFO size in number of bytes (has to be divisible by @c item_size)
uint16_t item_size; //!< Size of a single FIFO item
NRF_LOG_INSTANCE_PTR_DECLARE(p_log) //!< Pointer to instance of the logger object (Conditionally compiled).
}nrf_atfifo_t;
/**
* @brief FIFO write operation item context.
*
* Context structure used to mark an allocated space in FIFO that is ready for put.
* All the data required to properly put allocated and written data.
*/
typedef struct nrf_atfifo_item_put_s
{
nrf_atfifo_postag_t last_tail; //!< Tail tag value that was here when opening the FIFO to write
}nrf_atfifo_item_put_t;
/**
* @brief FIFO read operation item context.
*
* Context structure used to mark an opened get operation to properly free an item after reading.
*/
typedef struct nrf_atfifo_rcontext_s
{
nrf_atfifo_postag_t last_head; //!< Head tag value that was here when opening the FIFO to read
}nrf_atfifo_item_get_t;
/** @brief Name of the module used for logger messaging.
*/
#define NRF_ATFIFO_LOG_NAME atfifo
/**
* @defgroup nrf_atfifo_instmacros FIFO instance macros
*
* A group of macros helpful for FIFO instance creation and initialization.
* They may be used to create and initialize instances for most use cases.
*
* FIFO may also be created and initialized directly using
* @ref nrf_atfifo_init function.
* @{
*/
/**
* @brief Macro for generating the name for a data buffer.
*
* The name of the data buffer that would be created by
* @ref NRF_ATFIFO_DEF macro.
*
* @param[in] fifo_id Identifier of the FIFO object.
*
* @return Name of the buffer variable.
*
* @note This is auxiliary internal macro and in normal usage
* it should not be called.
*/
#define NRF_ATFIFO_BUF_NAME(fifo_id) CONCAT_2(fifo_id, _data)
/**
* @brief Macro for generating the name for a FIFO instance.
*
* The name of the instance variable that will be created by the
* @ref NRF_ATFIFO_DEF macro.
*
* @param[in] fifo_id Identifier of the FIFO object.
*
* @return Name of the instance variable.
*
* @note This is auxiliary internal macro and in normal usage
* it should not be called.
*/
#define NRF_ATFIFO_INST_NAME(fifo_id) CONCAT_2(fifo_id, _inst)
/**
* @brief Macro for creating an instance.
*
* Creates the FIFO object variable itself.
*
* Usage example:
* @code
* NRF_ATFIFO_DEF(my_fifo, uint16_t, 12);
* NRF_ATFIFO_INIT(my_fifo);
*
* uint16_t some_val = 45;
* nrf_atfifo_item_put(my_fifo, &some_val, sizeof(some_val), NULL);
* nrf_atfifo_item_get(my_fifo, &some_val, sizeof(some_val), NULL);
* @endcode
*
* @param[in] fifo_id Identifier of a FIFO object.
* This identifier will be a pointer to the instance.
* It makes it possible to use this directly for the functions
* that operate on the FIFO.
* Because it is a static const object, it should be optimized by the compiler.
* @param[in] storage_type Type of data that will be stored in the FIFO.
* @param[in] item_cnt Capacity of the created FIFO in maximum number of items that may be stored.
* The phisical size of the buffer will be 1 element bigger.
*/
#define NRF_ATFIFO_DEF(fifo_id, storage_type, item_cnt) \
static storage_type NRF_ATFIFO_BUF_NAME(fifo_id)[(item_cnt)+1]; \
NRF_LOG_INSTANCE_REGISTER(NRF_ATFIFO_LOG_NAME, fifo_id, \
NRF_ATFIFO_CONFIG_INFO_COLOR, \
NRF_ATFIFO_CONFIG_DEBUG_COLOR, \
NRF_ATFIFO_CONFIG_LOG_INIT_FILTER_LEVEL, \
NRF_ATFIFO_CONFIG_LOG_ENABLED ? \
NRF_ATFIFO_CONFIG_LOG_LEVEL : NRF_LOG_SEVERITY_NONE); \
static nrf_atfifo_t NRF_ATFIFO_INST_NAME(fifo_id) = { \
.p_buf = NULL, \
NRF_LOG_INSTANCE_PTR_INIT(p_log, NRF_ATFIFO_LOG_NAME, fifo_id) \
}; \
static nrf_atfifo_t * const fifo_id = &NRF_ATFIFO_INST_NAME(fifo_id)
/**
* @brief Macro for initializing the FIFO that was previously declared by the macro.
*
* Use this macro to simplify FIFO initialization.
*
* @note
* This macro can be only used on a FIFO object defined by @ref NRF_ATFIFO_DEF macro.
*
* @param[in] fifo_id Identifier of the FIFO object.
*
* @return Value from the @ref nrf_atfifo_init function.
*/
#define NRF_ATFIFO_INIT(fifo_id) \
nrf_atfifo_init( \
fifo_id, \
NRF_ATFIFO_BUF_NAME(fifo_id), \
sizeof(NRF_ATFIFO_BUF_NAME(fifo_id)), \
sizeof(NRF_ATFIFO_BUF_NAME(fifo_id)[0]) \
)
/** @} */
/**
* @brief Function for initializing the FIFO.
*
* Preparing the FIFO instance to work.
*
* @param[out] p_fifo FIFO object to initialize.
* @param[in,out] p_buf FIFO buffer for storing data.
* @param[in] buf_size Total buffer size (has to be divisible by @c item_size).
* @param[in] item_size Size of a single item held inside the FIFO.
*
* @retval NRF_SUCCESS If initialization was successful.
* @retval NRF_ERROR_NULL If a NULL pointer is provided as the buffer.
* @retval NRF_ERROR_INVALID_LENGTH If size of the buffer provided is not divisible by @c item_size.
*
* @note
* Buffer size must be able to hold one element more than the designed FIFO capacity.
* This one, empty element is used for overflow checking.
*/
ret_code_t nrf_atfifo_init(nrf_atfifo_t * const p_fifo, void * p_buf, uint16_t buf_size, uint16_t item_size);
/**
* @brief Function for clearing the FIFO.
*
* Function for clearing the FIFO.
*
* If this function is called during an opened and uncommitted write operation,
* the FIFO is cleared up to the currently ongoing commit.
* There is no possibility to cancel an ongoing commit.
*
* If this function is called during an opened and unflushed read operation,
* the read position in the head is set, but copying it into the write head position
* is left to read closing operation.
*
* This way, there is no more data to read, but the memory is released
* in the moment when it is safe.
*
* @param[in,out] p_fifo FIFO object.
*
* @retval NRF_SUCCESS FIFO totally cleared.
* @retval NRF_ERROR_BUSY Function called in the middle of writing or reading operation.
* If it is called in the middle of writing operation,
* FIFO was cleared up to the already started and uncommitted write.
* If it is called in the middle of reading operation,
* write head was only moved. It will be copied into read tail when the reading operation
* is flushed.
*/
ret_code_t nrf_atfifo_clear(nrf_atfifo_t * const p_fifo);
/**
* @brief Function for atomically putting data into the FIFO.
*
* It uses memcpy function inside and in most situations, it is more suitable to
* use @ref nrf_atfifo_item_alloc, write the data, and @ref nrf_atfifo_item_put to store a new value
* in a FIFO.
*
* @param[in,out] p_fifo FIFO object.
* @param[in] p_var Variable to copy.
* @param[in] size Size of the variable to copy.
* Can be smaller or equal to the FIFO item size.
* @param[out] p_visible See value returned by @ref nrf_atfifo_item_put.
* It may be NULL if the caller does not require the current operation status.
*
* @retval NRF_SUCCESS If an element has been successfully added to the FIFO.
* @retval NRF_ERROR_NO_MEM If the FIFO is full.
*
* @note
* To avoid data copying, you can use the @ref nrf_atfifo_item_alloc and @ref nrf_atfifo_item_put
* functions pair.
*/
ret_code_t nrf_atfifo_alloc_put(nrf_atfifo_t * const p_fifo, void const * const p_var, size_t size, bool * const p_visible);
/**
* @brief Function for opening the FIFO for writing.
*
* Function called to start the FIFO write operation and access the given FIFO buffer directly.
*
* @param[in,out] p_fifo FIFO object.
* @param[out] p_context Operation context, required by @ref nrf_atfifo_item_put.
*
* @return Pointer to the space where variable data can be stored.
* NULL if there is no space in the buffer.
*/
void * nrf_atfifo_item_alloc(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context);
/**
* @brief Function for closing the writing operation.
*
* Puts a previously allocated context into FIFO.
* This function must be called to commit an opened write operation.
* It sets all the buffers and marks the data, so that it is visible to read.
*
* @param[in,out] p_fifo FIFO object.
* @param[in] p_context Operation context, filled by the @ref nrf_atfifo_item_alloc function.
*
* @retval true Data is currently ready and will be visible to read.
* @retval false The internal commit was marked, but the writing operation interrupted another writing operation.
* The data will be available to read when the interrupted operation is committed.
*/
bool nrf_atfifo_item_put(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_put_t * p_context);
/**
* @brief Function for getting a single value from the FIFO.
*
* This function gets the value from the top of the FIFO.
* The value is removed from the FIFO memory.
*
* @param[in,out] p_fifo FIFO object.
* @param[out] p_var Pointer to the variable to store the data.
* @param[in] size Size of the data to be loaded.
* @param[out] p_released See the values returned by @ref nrf_atfifo_item_free.
*
* @retval NRF_SUCCESS Element was successfully copied from the FIFO memory.
* @retval NRF_ERROR_NOT_FOUND No data in the FIFO.
*/
ret_code_t nrf_atfifo_get_free(nrf_atfifo_t * const p_fifo, void * const p_var, size_t size, bool * p_released);
/**
* @brief Function for opening the FIFO for reading.
*
* Function called to start the FIFO read operation and access the given FIFO buffer directly.
*
* @param[in,out] p_fifo FIFO object.
* @param[out] p_context The operation context, required by @ref nrf_atfifo_item_free
*
* @return Pointer to data buffer or NULL if there is no data in the FIFO.
*/
void * nrf_atfifo_item_get(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context);
/**
* @brief Function for closing the reading operation.
*
* Function used to finish the reading operation.
* If this reading operation does not interrupt another reading operation, the head write buffer is moved.
* If this reading operation is placed in the middle of another reading, only the new read pointer is written.
*
* @param[in,out] p_fifo FIFO object.
* @param[in] p_context Context of the reading operation to be closed.
*
* @retval true This operation is not generated in the middle of another read operation and the write head will be updated to the read head (space is released).
* @retval false This operation was performed in the middle of another read operation and the write buffer head was not moved (no space is released).
*/
bool nrf_atfifo_item_free(nrf_atfifo_t * const p_fifo, nrf_atfifo_item_get_t * p_context);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* NRF_ATFIFO_H__ */

View File

@ -0,0 +1,578 @@
/**
* Copyright (c) 2011 - 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
* @brief Atomic FIFO internal file
*
* This file should be included only by nrf_atfifo internally.
* Needs nrf_atfifo.h included first.
*/
#ifndef NRF_ATFIFO_H__
#error This is internal file. Do not include this file in your program.
#endif
#ifndef NRF_ATFIFO_INTERNAL_H__
#define NRF_ATFIFO_INTERNAL_H__
#include <stddef.h>
#include "nrf.h"
#include "app_util.h"
#include "nordic_common.h"
#if ((__CORTEX_M >= 0x03U) || (__CORTEX_SC >= 300U)) == 0
#error Unsupported core version
#endif
/*
* Make sure that rd and wr pos in a tag are aligned like expected
* Changing this would require changes inside assembly code!
*/
// Mbed - saving for later... we run armcc in a gcc mode and this is causigg a problem
// STATIC_ASSERT(offsetof(nrf_atfifo_postag_pos_t, wr) == 0);
// STATIC_ASSERT(offsetof(nrf_atfifo_postag_pos_t, rd) == 2);
/**
* @brief Atomically reserve space for a new write.
*
* @param[in,out] p_fifo FIFO object.
* @param[out] old_tail Tail position tag before new space is reserved.
*
* @retval true Space available.
* @retval false Memory full.
*
* @sa nrf_atfifo_wspace_close
*/
static bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail);
/**
* @brief Atomically mark all written data available.
*
* This function marks all data available for reading.
* This marking is done by copying tail.pos.wr into tail.pos.rd.
*
* It must be called only when closing the first write.
* It cannot be called if any write access was interrupted.
* See the code below:
* @code
* if (old_tail.pos.wr == old_tail.pos.rd)
* {
* nrf_atfifo_wspace_close(my_fifo);
* return true;
* }
* return false;
* @endcode
*
* @param[in,out] p_fifo FIFO object.
*
* @sa nrf_atfifo_wspace_req
*/
static void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo);
/**
* @brief Atomically get a part of a buffer to read data.
*
* @param[in,out] p_fifo FIFO object.
* @param[out] old_head Head position tag before the data buffer is read.
*
* @retval true Data available for reading.
* @retval false No data in the buffer.
*
* @sa nrf_atfifo_rspace_close
*/
static bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head);
/**
* @brief Atomically release all read data.
*
* This function marks all data that was read as free space,
* which is available for writing.
* This marking is done by copying head.pos.rd into head.pos.wr.
*
* It must be called only when closing the first read.
* It cannot be called when the current read access interrupted any other read access.
* See code below:
* @code
* if (old_head.pos.wr == old_head.pos.rd)
* {
* nrf_atfifo_rspace_close(my_fifo);
* return true;
* }
* return false;
* @endcode
*
* @param[in,out] p_fifo FIFO object.
*
* @sa nrf_atfifo_rspace_req
*/
static void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo);
/**
* @brief Safely clear the FIFO, internal function.
*
* This function realizes the functionality required by @ref nrf_atfifo_clear.
*
* @param[in,out] p_fifo FIFO object.
*
* @retval true All the data was released.
* @retval false All the data available for releasing was released, but there is some pending transfer.
*/
static bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo);
/* ---------------------------------------------------------------------------
* Implementation starts here
*/
#if defined ( __CC_ARM )
__ASM bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail)
{
/* Registry usage:
* R0 - p_fifo
* R1 - p_old_tail
* R2 - internal variable old_tail (saved by caller)
* R3 - internal variable new_tail (saved by caller)
* R4 - internal temporary register (saved by this function)
* R5 - not used stored to keep the stack aligned to 8 bytes
* Returned value:
* R0 (bool - 32 bits)
*/
push {r4, r5}
nrf_atfifo_wspace_req_repeat
/* Load tail tag and set memory monitor !!! R2 - old tail !!! */
ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))]
/* Extract write position !!! R3 !!! */
uxth r3, r2
/* Increment address with overload support !!! R4 used temporary !!! */
ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, item_size))]
add r3, r4
ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, buf_size))]
cmp r3, r4
it hs
subhs r3, r3, r4
/* Check if FIFO would overload after making this increment !!! R4 used temporary !!! */
ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, head) + offsetof(nrf_atfifo_postag_pos_t, wr))]
cmp r3, r4
ittt eq
clrexeq
moveq r0, #__cpp(false)
beq nrf_atfifo_wspace_req_exit
/* Pack everything back !!! R3 - new tail !!! */
/* Copy lower byte from new_tail, and higher byte is a value from the top of old_tail */
pkhbt r3, r3, r2
/* Store new value clearing memory monitor !!! R4 used temporary !!! */
strex r4, r3, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))]
cmp r4, #0
bne nrf_atfifo_wspace_req_repeat
/* Return true */
mov r0, #__cpp(true)
nrf_atfifo_wspace_req_exit
/* Save old tail */
str r2, [r1]
pop {r4, r5}
bx lr
}
__ASM void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo)
{
/* Registry usage:
* R0 - p_fifo
* R1 - internal temporary register
* R2 - new_tail
*/
nrf_atfifo_wspace_close_repeat
ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))]
/* Copy from lower byte to higher */
pkhbt r2, r2, r2, lsl #16
strex r1, r2, [r0, #__cpp(offsetof(nrf_atfifo_t, tail))]
cmp r1, #0
bne nrf_atfifo_wspace_close_repeat
bx lr
}
__ASM bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head)
{
/* Registry usage:
* R0 - p_fifo
* R1 - p_old_head
* R2 - internal variable old_head (saved by caller)
* R3 - internal variable new_head (saved by caller)
* R4 - internal temporary register (saved by this function)
* R5 - not used stored to keep the stack aligned to 8 bytes
* Returned value:
* R0 (bool - 32 bits)
*/
push {r4, r5}
nrf_atfifo_rspace_req_repeat
/* Load tail tag and set memory monitor !!! R2 - old tail !!! */
ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))]
/* Extract read position !!! R3 !!! */
uxth r3, r2, ror #16
/* Check if we have any data !!! R4 used temporary !!! */
ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd))]
cmp r3, r4
ittt eq
clrexeq
moveq r0, #__cpp(false)
beq nrf_atfifo_rspace_req_exit
/* Increment address with overload support !!! R4 used temporary !!! */
ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, item_size))]
add r3, r4
ldrh r4, [r0, #__cpp(offsetof(nrf_atfifo_t, buf_size))]
cmp r3, r4
it hs
subhs r3, r3, r4
/* Pack everything back !!! R3 - new tail !!! */
/* Copy lower byte from old_head, and higher byte is a value from write_pos */
pkhbt r3, r2, r3, lsl #16
/* Store new value clearing memory monitor !!! R4 used temporary !!! */
strex r4, r3, [r0, #__cpp(offsetof(nrf_atfifo_t, head))]
cmp r4, #0
bne nrf_atfifo_rspace_req_repeat
/* Return true */
mov r0, #__cpp(true)
nrf_atfifo_rspace_req_exit
/* Save old head */
str r2, [r1]
pop {r4, r5}
bx lr
}
__ASM void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo)
{
/* Registry usage:
* R0 - p_fifo
* R1 - internal temporary register
* R2 - new_tail
*/
nrf_atfifo_rspace_close_repeat
ldrex r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))]
/* Copy from higher byte to lower */
pkhtb r2, r2, r2, asr #16
strex r1, r2, [r0, #__cpp(offsetof(nrf_atfifo_t, head))]
cmp r1, #0
bne nrf_atfifo_rspace_close_repeat
bx lr
}
__ASM bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo)
{
/* Registry usage:
* R0 - p_fifo as input, bool output after
* R1 - tail, rd pointer, new_head
* R2 - head_old, destroyed when creating new_head
* R3 - p_fifo - copy
*/
mov r3, r0
nrf_atfifo_space_clear_repeat
/* Load old head in !!! R2 register !!! and read pointer of tail in !!! R1 register !!! */
ldrex r2, [r3, #__cpp(offsetof(nrf_atfifo_t, head))]
ldrh r1, [r3, #__cpp(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd))]
cmp r2, r2, ror #16
/* Return false as default */
mov r0, #__cpp(false)
/* Create new head in !!! R1 register !!! Data in !!! R2 register broken !!! */
itett ne
uxthne r2, r2
orreq r1, r1, r1, lsl #16
orrne r1, r2, r1, lsl #16
/* Skip header test */
bne nrf_atfifo_space_clear_head_test_skip
/* Load whole tail and test it !!! R2 used !!! */
ldr r2, [r3, #__cpp(offsetof(nrf_atfifo_t, tail))]
cmp r2, r2, ror #16
/* Return true if equal */
it eq
moveq r0, #__cpp(true)
nrf_atfifo_space_clear_head_test_skip
/* Store and test if success !!! R2 used temporary !!! */
strex r2, r1, [r3, #__cpp(offsetof(nrf_atfifo_t, head))]
cmp r2, #0
bne nrf_atfifo_space_clear_repeat
bx lr
}
#elif defined ( __ICCARM__ ) || defined ( __GNUC__ )
bool nrf_atfifo_wspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_tail)
{
volatile bool ret;
volatile uint32_t old_tail;
uint32_t new_tail;
uint32_t temp;
__ASM volatile(
/* For more comments see Keil version above */
"1: \n"
" ldrex %[old_tail], [%[p_fifo], %[offset_tail]] \n"
" uxth %[new_tail], %[old_tail] \n"
" \n"
" ldrh %[temp], [%[p_fifo], %[offset_item_size]] \n"
" add %[new_tail], %[temp] \n"
" ldrh %[temp], [%[p_fifo], %[offset_buf_size]] \n"
" cmp %[new_tail], %[temp] \n"
" it hs \n"
" subhs %[new_tail], %[new_tail], %[temp] \n"
" \n"
" ldrh %[temp], [%[p_fifo], %[offset_head_wr]] \n"
" cmp %[new_tail], %[temp] \n"
" ittt eq \n"
" clrexeq \n"
" moveq %[ret], %[false_val] \n"
" beq.n 2f \n"
" \n"
" pkhbt %[new_tail], %[new_tail], %[old_tail] \n"
" \n"
" strex %[temp], %[new_tail], [%[p_fifo], %[offset_tail]] \n"
" cmp %[temp], #0 \n"
" bne.n 1b \n"
" \n"
" mov %[ret], %[true_val] \n"
"2: \n"
: /* Output operands */
[ret] "=r"(ret),
[temp] "=&r"(temp),
[old_tail]"=&r"(old_tail),
[new_tail]"=&r"(new_tail)
: /* Input operands */
[p_fifo] "r"(p_fifo),
[offset_tail] "J"(offsetof(nrf_atfifo_t, tail)),
[offset_head_wr] "J"(offsetof(nrf_atfifo_t, head) + offsetof(nrf_atfifo_postag_pos_t, wr)),
[offset_item_size]"J"(offsetof(nrf_atfifo_t, item_size)),
[offset_buf_size] "J"(offsetof(nrf_atfifo_t, buf_size)),
[true_val] "I"(true),
[false_val] "I"(false)
: /* Clobbers */
"cc");
p_old_tail->tag = old_tail;
UNUSED_VARIABLE(new_tail);
UNUSED_VARIABLE(temp);
return ret;
}
void nrf_atfifo_wspace_close(nrf_atfifo_t * const p_fifo)
{
uint32_t temp;
uint32_t new_tail;
__ASM volatile(
/* For more comments see Keil version above */
"1: \n"
" ldrex %[new_tail], [%[p_fifo], %[offset_tail]] \n"
" pkhbt %[new_tail],%[new_tail], %[new_tail], lsl #16 \n"
" \n"
" strex %[temp], %[new_tail], [%[p_fifo], %[offset_tail]] \n"
" cmp %[temp], #0 \n"
" bne.n 1b \n"
: /* Output operands */
[temp] "=&r"(temp),
[new_tail] "=&r"(new_tail)
: /* Input operands */
[p_fifo] "r"(p_fifo),
[offset_tail] "J"(offsetof(nrf_atfifo_t, tail))
: /* Clobbers */
"cc");
UNUSED_VARIABLE(temp);
UNUSED_VARIABLE(new_tail);
}
bool nrf_atfifo_rspace_req(nrf_atfifo_t * const p_fifo, nrf_atfifo_postag_t * const p_old_head)
{
volatile bool ret;
volatile uint32_t old_head;
uint32_t new_head;
uint32_t temp;
__ASM volatile(
/* For more comments see Keil version above */
"1: \n"
" ldrex %[old_head], [%[p_fifo], %[offset_head]] \n"
" uxth %[new_head], %[old_head], ror #16 \n"
" \n"
" ldrh %[temp], [%[p_fifo], %[offset_tail_rd]] \n"
" cmp %[new_head], %[temp] \n"
" ittt eq \n"
" clrexeq \n"
" moveq %[ret], %[false_val] \n"
" beq.n 2f \n"
" \n"
" ldrh %[temp], [%[p_fifo], %[offset_item_size]] \n"
" add %[new_head], %[temp] \n"
" ldrh %[temp], [%[p_fifo], %[offset_buf_size]] \n"
" cmp %[new_head], %[temp] \n"
" it hs \n"
" subhs %[new_head], %[new_head], %[temp] \n"
" \n"
" pkhbt %[new_head], %[old_head], %[new_head], lsl #16 \n"
" \n"
" strex %[temp], %[new_head], [%[p_fifo], %[offset_head]] \n"
" cmp %[temp], #0 \n"
" bne.n 1b \n"
" \n"
" mov %[ret], %[true_val] \n"
"2: \n"
: /* Output operands */
[ret] "=r"(ret),
[temp] "=&r"(temp),
[old_head]"=&r"(old_head),
[new_head]"=&r"(new_head)
: /* Input operands */
[p_fifo] "r"(p_fifo),
[offset_head] "J"(offsetof(nrf_atfifo_t, head)),
[offset_tail_rd] "J"(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd)),
[offset_item_size]"J"(offsetof(nrf_atfifo_t, item_size)),
[offset_buf_size] "J"(offsetof(nrf_atfifo_t, buf_size)),
[true_val] "I"(true),
[false_val] "I"(false)
: /* Clobbers */
"cc");
p_old_head->tag = old_head;
UNUSED_VARIABLE(new_head);
UNUSED_VARIABLE(temp);
return ret;
}
void nrf_atfifo_rspace_close(nrf_atfifo_t * const p_fifo)
{
uint32_t temp;
uint32_t new_head;
__ASM volatile(
/* For more comments see Keil version above */
"1: \n"
" ldrex %[new_head], [%[p_fifo], %[offset_head]] \n"
" pkhtb %[new_head],%[new_head], %[new_head], asr #16 \n"
" \n"
" strex %[temp], %[new_head], [%[p_fifo], %[offset_head]] \n"
" cmp %[temp], #0 \n"
" bne.n 1b \n"
: /* Output operands */
[temp] "=&r"(temp),
[new_head] "=&r"(new_head)
: /* Input operands */
[p_fifo] "r"(p_fifo),
[offset_head] "J"(offsetof(nrf_atfifo_t, head))
: /* Clobbers */
"cc");
UNUSED_VARIABLE(temp);
UNUSED_VARIABLE(new_head);
}
bool nrf_atfifo_space_clear(nrf_atfifo_t * const p_fifo)
{
volatile bool ret;
uint32_t old_head; /* This variable is left broken after assembly code finishes */
uint32_t new_head;
__ASM volatile(
"1: \n"
" ldrex %[old_head], [%[p_fifo], %[offset_head]] \n"
" ldrh %[new_head], [%[p_fifo], %[offset_tail_rd]] \n"
" cmp %[old_head], %[old_head], ror #16 \n"
" \n"
" mov %[ret], %[false_val] \n"
" \n"
" itett ne \n"
" uxthne %[old_head], %[old_head] \n"
" orreq %[new_head], %[new_head], %[new_head], lsl #16 \n"
" orrne %[new_head], %[old_head], %[new_head], lsl #16 \n"
" \n"
" bne.n 2f \n"
" \n"
" ldr %[old_head], [%[p_fifo], %[offset_tail]] \n"
" cmp %[old_head], %[old_head], ror #16 \n"
" it eq \n"
" moveq %[ret], %[true_val] \n"
" \n"
"2: \n"
" strex %[old_head], %[new_head], [%[p_fifo], %[offset_head]] \n"
" cmp %[old_head], #0 \n"
" bne.n 1b \n"
: /* Output operands */
[ret] "=&r"(ret),
[old_head] "=&r"(old_head),
[new_head] "=&r"(new_head)
: /* Input operands */
[p_fifo] "r"(p_fifo),
[offset_head] "J"(offsetof(nrf_atfifo_t, head)),
[offset_tail] "J"(offsetof(nrf_atfifo_t, tail)),
[offset_tail_rd] "J"(offsetof(nrf_atfifo_t, tail) + offsetof(nrf_atfifo_postag_pos_t, rd)),
[true_val] "I"(true),
[false_val] "I"(false)
: /* Clobbers */
"cc");
UNUSED_VARIABLE(old_head);
UNUSED_VARIABLE(new_head);
return ret;
}
#else
#error Unsupported compiler
#endif
#endif /* NRF_ATFIFO_INTERNAL_H__ */

View File

@ -0,0 +1,399 @@
/**
* 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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_BALLOC)
#include "nrf_section.h"
#include "nrf_balloc.h"
#include "app_util_platform.h"
#if NRF_BALLOC_CONFIG_LOG_ENABLED
#define NRF_LOG_LEVEL NRF_BALLOC_CONFIG_LOG_LEVEL
#define NRF_LOG_INITIAL_LEVEL NRF_BALLOC_CONFIG_INITIAL_LOG_LEVEL
#define NRF_LOG_INFO_COLOR NRF_BALLOC_CONFIG_INFO_COLOR
#define NRF_LOG_DEBUG_COLOR NRF_BALLOC_CONFIG_DEBUG_COLOR
#else
#define NRF_LOG_LEVEL 0
#endif // NRF_BALLOC_CONFIG_LOG_ENABLED
#include "nrf_log.h"
#define HEAD_GUARD_FILL 0xBAADF00D /**< Magic number used to mark head guard.*/
#define TAIL_GUARD_FILL 0xBAADCAFE /**< Magic number used to mark tail guard.*/
#define FREE_MEM_FILL 0xBAADBAAD /**< Magic number used to mark free memory.*/
#if NRF_BALLOC_CONFIG_DEBUG_ENABLED
#define POOL_ID(_p_pool) _p_pool->p_name
#define POOL_MARKER "%s"
#else
#define POOL_ID(_p_pool) _p_pool
#define POOL_MARKER "0x%08X"
#endif
NRF_SECTION_DEF(nrf_balloc, nrf_balloc_t);
#if NRF_BALLOC_CLI_CMDS
#include "nrf_cli.h"
static void nrf_balloc_status(nrf_cli_t const * p_cli, size_t argc, char **argv)
{
UNUSED_PARAMETER(argv);
if (nrf_cli_help_requested(p_cli))
{
nrf_cli_help_print(p_cli, NULL, 0);
return;
}
if (argc > 1)
{
nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Bad argument count");
return;
}
uint32_t num_of_instances = NRF_SECTION_ITEM_COUNT(nrf_balloc, nrf_balloc_t);
uint32_t i;
for (i = 0; i < num_of_instances; i++)
{
const nrf_balloc_t * p_instance = NRF_SECTION_ITEM_GET(nrf_balloc, nrf_balloc_t, i);
uint32_t element_size = NRF_BALLOC_ELEMENT_SIZE(p_instance);
uint32_t dbg_addon = p_instance->block_size - element_size;
uint32_t pool_size = p_instance->p_stack_limit - p_instance->p_stack_base;
uint32_t max_util = nrf_balloc_max_utilization_get(p_instance);
uint32_t util = nrf_balloc_utilization_get(p_instance);
const char * p_name = p_instance->p_name;
nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL,
"%s\r\n\t- Element size:\t%d + %d bytes of debug information\r\n"
"\t- Usage:\t%u%% (%u out of %u elements)\r\n"
"\t- Maximum:\t%u%% (%u out of %u elements)\r\n\r\n",
p_name, element_size, dbg_addon,
100ul * util/pool_size, util,pool_size,
100ul * max_util/pool_size, max_util,pool_size);
}
}
// Register "balloc" command and its subcommands in CLI.
NRF_CLI_CREATE_STATIC_SUBCMD_SET(nrf_balloc_commands)
{
NRF_CLI_CMD(status, NULL, "Print status of balloc instances.", nrf_balloc_status),
NRF_CLI_SUBCMD_SET_END
};
NRF_CLI_CMD_REGISTER(balloc, &nrf_balloc_commands, "Commands for BALLOC management", nrf_balloc_status);
#endif //NRF_BALLOC_CLI_CMDS
#if NRF_BALLOC_CONFIG_DEBUG_ENABLED
/**@brief Validate block memory, prepare block guards, and calculate pointer to the element.
*
* @param[in] p_pool Pointer to the memory pool.
* @param[in] p_head Pointer to the beginning of the block.
*
* @return Pointer to the element.
*/
__STATIC_INLINE void * nrf_balloc_block_unwrap(nrf_balloc_t const * p_pool, void * p_head)
{
ASSERT((p_pool != NULL) && ((p_pool->block_size % sizeof(uint32_t)) == 0));
ASSERT((p_head != NULL) && (((uint32_t)(p_head) % sizeof(uint32_t)) == 0));
uint32_t head_words = NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET(p_pool->debug_flags);
uint32_t tail_words = NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET(p_pool->debug_flags);
uint32_t * p_tail = (uint32_t *)((size_t)(p_head) + p_pool->block_size);
uint32_t * p_element = (uint32_t *)p_head + head_words;
if (NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_GET(p_pool->debug_flags))
{
for (uint32_t * ptr = p_head; ptr < p_tail; ptr++)
{
if (*ptr != FREE_MEM_FILL)
{
NRF_LOG_INST_ERROR(p_pool->p_log,
"Detected free memory corruption at 0x%08X (0x%08X != 0x%08X)",
ptr, *ptr, FREE_MEM_FILL);
APP_ERROR_CHECK_BOOL(false);
}
}
}
for (uint32_t * ptr = p_head; ptr < p_element; ptr++)
{
*ptr = HEAD_GUARD_FILL;
}
for (uint32_t * ptr = ( p_tail - tail_words); ptr < p_tail; ptr++)
{
*ptr = TAIL_GUARD_FILL;
}
return p_element;
}
/**@brief Calculate pointer to the block, validate block guards, and mark block memory as free.
*
* @param[in] p_pool Pointer to the memory pool.
* @param[in] p_element Pointer to the element.
*
* @return Pointer to the beginning of the block.
*/
__STATIC_INLINE void * nrf_balloc_element_wrap(nrf_balloc_t const * p_pool, void * p_element)
{
ASSERT((p_pool != NULL) && ((p_pool->block_size % sizeof(uint32_t)) == 0));
ASSERT((p_element != NULL) && (((uint32_t)(p_element) % sizeof(uint32_t)) == 0));
uint32_t head_words = NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET(p_pool->debug_flags);
uint32_t tail_words = NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET(p_pool->debug_flags);
uint32_t * p_head = (uint32_t *)p_element - head_words;
uint32_t * p_tail = (uint32_t *)((size_t)(p_head) + p_pool->block_size);
for (uint32_t * ptr = p_head; ptr < (uint32_t *)p_element; ptr++)
{
if (*ptr != HEAD_GUARD_FILL)
{
NRF_LOG_INST_ERROR(p_pool->p_log,
"Detected Head Guard corruption at 0x%08X (0x%08X != 0x%08X)",
ptr, *ptr, HEAD_GUARD_FILL);
APP_ERROR_CHECK_BOOL(false);
}
}
for (uint32_t * ptr = ( p_tail - tail_words); ptr < p_tail; ptr++)
{
if (*ptr != TAIL_GUARD_FILL)
{
NRF_LOG_INST_ERROR(p_pool->p_log,
"Detected Tail Guard corruption at 0x%08X (0x%08X != 0x%08X)",
ptr, *ptr, TAIL_GUARD_FILL);
APP_ERROR_CHECK_BOOL(false);
}
}
if (NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_GET(p_pool->debug_flags))
{
for (uint32_t * ptr = p_head; ptr < p_tail; ptr++)
{
*ptr = FREE_MEM_FILL;
}
}
return p_head;
}
#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED
/**@brief Convert block index to a pointer.
*
* @param[in] p_pool Pointer to the memory pool.
* @param[in] idx Index of the block.
*
* @return Pointer to the beginning of the block.
*/
static void * nrf_balloc_idx2block(nrf_balloc_t const * p_pool, uint8_t idx)
{
ASSERT(p_pool != NULL);
return (uint8_t *)(p_pool->p_memory_begin) + ((size_t)(idx) * p_pool->block_size);
}
/**@brief Convert block pointer to index.
*
* @param[in] p_pool Pointer to the memory pool.
* @param[in] p_block Pointer to the beginning of the block.
*
* @return Index of the block.
*/
static uint8_t nrf_balloc_block2idx(nrf_balloc_t const * p_pool, void const * p_block)
{
ASSERT(p_pool != NULL);
return ((size_t)(p_block) - (size_t)(p_pool->p_memory_begin)) / p_pool->block_size;
}
ret_code_t nrf_balloc_init(nrf_balloc_t const * p_pool)
{
uint8_t pool_size;
VERIFY_PARAM_NOT_NULL(p_pool);
ASSERT(p_pool->p_cb);
ASSERT(p_pool->p_stack_base);
ASSERT(p_pool->p_stack_limit);
ASSERT(p_pool->p_memory_begin);
ASSERT(p_pool->block_size);
pool_size = p_pool->p_stack_limit - p_pool->p_stack_base;
#if NRF_BALLOC_CONFIG_DEBUG_ENABLED
void *p_memory_end = (uint8_t *)(p_pool->p_memory_begin) + (pool_size * p_pool->block_size);
if (NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_GET(p_pool->debug_flags))
{
for (uint32_t * ptr = p_pool->p_memory_begin; ptr < (uint32_t *)(p_memory_end); ptr++)
{
*ptr = FREE_MEM_FILL;
}
}
#endif
NRF_LOG_INST_INFO(p_pool->p_log, "Initialized (size: %u x %u = %u bytes)",
pool_size,
p_pool->block_size,
pool_size * p_pool->block_size);
p_pool->p_cb->p_stack_pointer = p_pool->p_stack_base;
while (pool_size--)
{
*(p_pool->p_cb->p_stack_pointer)++ = pool_size;
}
p_pool->p_cb->max_utilization = 0;
return NRF_SUCCESS;
}
void * nrf_balloc_alloc(nrf_balloc_t const * p_pool)
{
ASSERT(p_pool != NULL);
void * p_block = NULL;
CRITICAL_REGION_ENTER();
if (p_pool->p_cb->p_stack_pointer > p_pool->p_stack_base)
{
// Allocate block.
p_block = nrf_balloc_idx2block(p_pool, *--(p_pool->p_cb->p_stack_pointer));
// Update utilization statistics.
uint8_t utilization = p_pool->p_stack_limit - p_pool->p_cb->p_stack_pointer;
if (p_pool->p_cb->max_utilization < utilization)
{
p_pool->p_cb->max_utilization = utilization;
}
}
CRITICAL_REGION_EXIT();
#if NRF_BALLOC_CONFIG_DEBUG_ENABLED
if (p_block != NULL)
{
p_block = nrf_balloc_block_unwrap(p_pool, p_block);
}
#endif
NRF_LOG_INST_DEBUG(p_pool->p_log, "Allocating element: 0x%08X", p_block);
return p_block;
}
void nrf_balloc_free(nrf_balloc_t const * p_pool, void * p_element)
{
ASSERT(p_pool != NULL);
ASSERT(p_element != NULL)
NRF_LOG_INST_DEBUG(p_pool->p_log, "Freeing element: 0x%08X", p_element);
#if NRF_BALLOC_CONFIG_DEBUG_ENABLED
void * p_block = nrf_balloc_element_wrap(p_pool, p_element);
// These checks could be done outside critical region as they use only pool configuration data.
if (NRF_BALLOC_DEBUG_BASIC_CHECKS_GET(p_pool->debug_flags))
{
uint8_t pool_size = p_pool->p_stack_limit - p_pool->p_stack_base;
void *p_memory_end = (uint8_t *)(p_pool->p_memory_begin) + (pool_size * p_pool->block_size);
// Check if the element belongs to this pool.
if ((p_block < p_pool->p_memory_begin) || (p_block >= p_memory_end))
{
NRF_LOG_INST_ERROR(p_pool->p_log,
"Attempted to free element (0x%08X) that does not belong to the pool.",
p_element);
APP_ERROR_CHECK_BOOL(false);
}
// Check if the pointer is valid.
if ((((size_t)(p_block) - (size_t)(p_pool->p_memory_begin)) % p_pool->block_size) != 0)
{
NRF_LOG_INST_ERROR(p_pool->p_log,
"Attempted to free corrupted element address (0x%08X).", p_element);
APP_ERROR_CHECK_BOOL(false);
}
}
#else
void * p_block = p_element;
#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED
CRITICAL_REGION_ENTER();
#if NRF_BALLOC_CONFIG_DEBUG_ENABLED
// These checks have to be done in critical region as they use p_pool->p_stack_pointer.
if (NRF_BALLOC_DEBUG_BASIC_CHECKS_GET(p_pool->debug_flags))
{
// Check for allocated/free ballance.
if (p_pool->p_cb->p_stack_pointer >= p_pool->p_stack_limit)
{
NRF_LOG_INST_ERROR(p_pool->p_log,
"Attempted to free an element (0x%08X) while the pool is full.",
p_element);
APP_ERROR_CHECK_BOOL(false);
}
}
if (NRF_BALLOC_DEBUG_DOUBLE_FREE_CHECK_GET(p_pool->debug_flags))
{
// Check for double free.
for (uint8_t * p_idx = p_pool->p_stack_base; p_idx < p_pool->p_cb->p_stack_pointer; p_idx++)
{
if (nrf_balloc_idx2block(p_pool, *p_idx) == p_block)
{
NRF_LOG_INST_ERROR(p_pool->p_log, "Attempted to double-free an element (0x%08X).",
p_element);
APP_ERROR_CHECK_BOOL(false);
}
}
}
#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED
// Free the element.
*(p_pool->p_cb->p_stack_pointer)++ = nrf_balloc_block2idx(p_pool, p_block);
CRITICAL_REGION_EXIT();
}
#endif // NRF_MODULE_ENABLED(NRF_BALLOC)

View File

@ -0,0 +1,351 @@
/**
* 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.
*
*/
/**
* @defgroup nrf_balloc Block memory allocator
* @{
* @ingroup app_common
* @brief This module handles block memory allocator features.
*/
#ifndef NRF_BALLOC_H__
#define NRF_BALLOC_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "sdk_errors.h"
#include "sdk_config.h"
#include "app_util_platform.h"
#include "app_util.h"
#include "nrf_log_instance.h"
#include "nrf_section.h"
/** @brief Name of the module used for logger messaging.
*/
#define NRF_BALLOC_LOG_NAME balloc
#if NRF_BALLOC_CONFIG_DEBUG_ENABLED || NRF_BALLOC_CLI_CMDS
#define NRF_BALLOC_HAS_NAME 1
#else
#define NRF_BALLOC_HAS_NAME 0
#endif
/**@defgroup NRF_BALLOC_DEBUG Macros for preparing debug flags for block allocator module.
* @{ */
#define NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_SET(words) (((words) & 0xFF) << 0)
#define NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET(flags) (((flags) >> 0) & 0xFF)
#define NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_SET(words) (((words) & 0xFF) << 8)
#define NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET(flags) (((flags) >> 8) & 0xFF)
#define NRF_BALLOC_DEBUG_BASIC_CHECKS_SET(enable) (!!(enable) << 16)
#define NRF_BALLOC_DEBUG_BASIC_CHECKS_GET(flags) (flags & (1 << 16))
#define NRF_BALLOC_DEBUG_DOUBLE_FREE_CHECK_SET(enable) (!!(enable) << 17)
#define NRF_BALLOC_DEBUG_DOUBLE_FREE_CHECK_GET(flags) (flags & (1 << 17))
#define NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_SET(enable) (!!(enable) << 18)
#define NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_GET(flags) (flags & (1 << 18))
/**@} */
/**@brief Default debug flags for @ref nrf_balloc. This is used by the @ref NRF_BALLOC_DEF macro.
* Flags can be changed in @ref sdk_config.
*/
#if NRF_BALLOC_CONFIG_DEBUG_ENABLED
#define NRF_BALLOC_DEFAULT_DEBUG_FLAGS \
( \
NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_SET(NRF_BALLOC_CONFIG_HEAD_GUARD_WORDS) | \
NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_SET(NRF_BALLOC_CONFIG_TAIL_GUARD_WORDS) | \
NRF_BALLOC_DEBUG_BASIC_CHECKS_SET(NRF_BALLOC_CONFIG_BASIC_CHECKS_ENABLED) | \
NRF_BALLOC_DEBUG_DOUBLE_FREE_CHECK_SET(NRF_BALLOC_CONFIG_DOUBLE_FREE_CHECK_ENABLED) | \
NRF_BALLOC_DEBUG_DATA_TRASHING_CHECK_SET(NRF_BALLOC_CONFIG_DATA_TRASHING_CHECK_ENABLED) \
)
#else
#define NRF_BALLOC_DEFAULT_DEBUG_FLAGS 0
#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED
/**@brief Block memory allocator control block.*/
typedef struct
{
uint8_t * p_stack_pointer; //!< Current allocation stack pointer.
uint8_t max_utilization; //!< Maximum utilization of the memory pool.
} nrf_balloc_cb_t;
/**@brief Block memory allocator pool instance. The pool is made of elements of the same size. */
typedef struct
{
nrf_balloc_cb_t * p_cb; //!< Pointer to the instance control block.
uint8_t * p_stack_base; //!< Base of the allocation stack.
/**<
* Stack is used to store handlers to not allocated elements.
*/
uint8_t * p_stack_limit; //!< Maximum possible value of the allocation stack pointer.
void * p_memory_begin; //!< Pointer to the start of the memory pool.
/**<
* Memory is used as a heap for blocks.
*/
NRF_LOG_INSTANCE_PTR_DECLARE(p_log) //!< Pointer to instance of the logger object (Conditionally compiled).
#if NRF_BALLOC_HAS_NAME
const char * p_name; //!< Pointer to string with pool name.
#endif
#if NRF_BALLOC_CONFIG_DEBUG_ENABLED
uint32_t debug_flags; //!< Debugging settings.
/**<
* Debug flag should be created by @ref NRF_BALLOC_DEBUG.
*/
#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED
uint16_t block_size; //!< Size of the allocated block (including debug overhead).
/**<
* Single block contains user element with header and tail
* words.
*/
} nrf_balloc_t;
/**@brief Get total memory consumed by single block (element size with overhead caused by debug
* flags).
*
* @param[in] _element_size Size of an element.
* @param[in] _debug_flags Debug flags.
*/
#if NRF_BALLOC_CONFIG_DEBUG_ENABLED
#define NRF_BALLOC_BLOCK_SIZE(_element_size, _debug_flags) \
( \
(sizeof(uint32_t) * NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET(_debug_flags)) + \
ALIGN_NUM(sizeof(uint32_t), (_element_size)) + \
(sizeof(uint32_t) * NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET(_debug_flags)) \
)
#else
#define NRF_BALLOC_BLOCK_SIZE(_element_size, _debug_flags) \
ALIGN_NUM(sizeof(uint32_t), (_element_size))
#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED
/**@brief Get element size ( excluding debugging overhead is present)
* flags).
*
* @param[in] _p_balloc Pointer to balloc instance.
*/
#if NRF_BALLOC_CONFIG_DEBUG_ENABLED
#define NRF_BALLOC_ELEMENT_SIZE(_p_balloc) \
(ALIGN_NUM(sizeof(uint32_t), (_p_balloc)->block_size) - \
((sizeof(uint32_t) * NRF_BALLOC_DEBUG_HEAD_GUARD_WORDS_GET((_p_balloc)->debug_flags)) + \
(sizeof(uint32_t) * NRF_BALLOC_DEBUG_TAIL_GUARD_WORDS_GET((_p_balloc)->debug_flags))))
#else
#define NRF_BALLOC_ELEMENT_SIZE(_p_balloc) \
(_p_balloc)->block_size
#endif // NRF_BALLOC_CONFIG_DEBUG_ENABLED
#if NRF_BALLOC_CONFIG_DEBUG_ENABLED
#define __NRF_BALLOC_ASSIGN_DEBUG_FLAGS(_debug_flags) .debug_flags = (_debug_flags),
#else
#define __NRF_BALLOC_ASSIGN_DEBUG_FLAGS(_debug_flags)
#endif
#if NRF_BALLOC_HAS_NAME
#define __NRF_BALLOC_ASSIGN_POOL_NAME(_name) .p_name = STRINGIFY(_name),
#else
#define __NRF_BALLOC_ASSIGN_POOL_NAME(_name)
#endif
/**@brief Create a block allocator instance with custom debug flags.
*
* @note This macro reserves memory for the given block allocator instance.
*
* @param[in] _name Name of the allocator.
* @param[in] _element_size Size of one element.
* @param[in] _pool_size Size of the pool.
* @param[in] _debug_flags Debug flags (@ref NRF_BALLOC_DEBUG).
*/
#define NRF_BALLOC_DBG_DEF(_name, _element_size, _pool_size, _debug_flags) \
STATIC_ASSERT((_pool_size) <= UINT8_MAX); \
static uint8_t CONCAT_2(_name, _nrf_balloc_pool_stack)[(_pool_size)]; \
static uint32_t CONCAT_2(_name,_nrf_balloc_pool_mem) \
[NRF_BALLOC_BLOCK_SIZE(_element_size, _debug_flags) * (_pool_size) / sizeof(uint32_t)]; \
static nrf_balloc_cb_t CONCAT_2(_name,_nrf_balloc_cb); \
NRF_LOG_INSTANCE_REGISTER(NRF_BALLOC_LOG_NAME, _name, \
NRF_BALLOC_CONFIG_INFO_COLOR, \
NRF_BALLOC_CONFIG_DEBUG_COLOR, \
NRF_BALLOC_CONFIG_INITIAL_LOG_LEVEL, \
NRF_BALLOC_CONFIG_LOG_ENABLED ? \
NRF_BALLOC_CONFIG_LOG_LEVEL : NRF_LOG_SEVERITY_NONE); \
NRF_SECTION_ITEM_REGISTER(nrf_balloc, const nrf_balloc_t _name) = \
{ \
.p_cb = &CONCAT_2(_name,_nrf_balloc_cb), \
.p_stack_base = CONCAT_2(_name,_nrf_balloc_pool_stack), \
.p_stack_limit = CONCAT_2(_name,_nrf_balloc_pool_stack) + (_pool_size), \
.p_memory_begin = CONCAT_2(_name,_nrf_balloc_pool_mem), \
.block_size = NRF_BALLOC_BLOCK_SIZE(_element_size, _debug_flags), \
\
NRF_LOG_INSTANCE_PTR_INIT(p_log, NRF_BALLOC_LOG_NAME, _name) \
__NRF_BALLOC_ASSIGN_POOL_NAME(_name) \
__NRF_BALLOC_ASSIGN_DEBUG_FLAGS(_debug_flags) \
}
/**@brief Create a block allocator instance.
*
* @note This macro reserves memory for the given block allocator instance.
*
* @param[in] _name Name of the allocator.
* @param[in] _element_size Size of one element.
* @param[in] _pool_size Size of the pool.
*/
#define NRF_BALLOC_DEF(_name, _element_size, _pool_size) \
NRF_BALLOC_DBG_DEF(_name, _element_size, _pool_size, NRF_BALLOC_DEFAULT_DEBUG_FLAGS)
/**@brief Create a block allocator interface.
*
* @param[in] _type Type which is allocated.
* @param[in] _name Name of the allocator.
*/
#define NRF_BALLOC_INTERFACE_DEC(_type, _name) \
_type * CONCAT_2(_name,_alloc)(void); \
void CONCAT_2(_name,_free)(_type * p_element)
/**@brief Define a custom block allocator interface.
*
* @param[in] _attr Function attribute that will be added to allocator function definition.
* @param[in] _type Type which is allocated.
* @param[in] _name Name of the allocator.
* @param[in] _p_pool Pool from which data will be allocated.
*/
#define NRF_BALLOC_INTERFACE_CUSTOM_DEF(_attr, _type, _name, _p_pool) \
_attr _type * CONCAT_2(_name,_alloc)(void) \
{ \
GCC_PRAGMA("GCC diagnostic push") \
GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \
ASSERT((_p_pool) != NULL); \
ASSERT((_p_pool)->block_size >= \
NRF_BALLOC_BLOCK_SIZE(sizeof(_type), (_p_pool)->debug_flags)); \
GCC_PRAGMA("GCC diagnostic pop") \
return (_type *)(nrf_balloc_alloc(_p_pool)); \
} \
\
_attr void CONCAT_2(_name,_free)(_type * p_element) \
{ \
GCC_PRAGMA("GCC diagnostic push") \
GCC_PRAGMA("GCC diagnostic ignored \"-Waddress\"") \
ASSERT((_p_pool) != NULL); \
ASSERT((_p_pool)->block_size >= \
NRF_BALLOC_BLOCK_SIZE(sizeof(_type), (_p_pool)->debug_flags)); \
GCC_PRAGMA("GCC diagnostic pop") \
nrf_balloc_free((_p_pool), p_element); \
}
/**@brief Define block allocator interface.
*
* @param[in] _type Type which is allocated.
* @param[in] _name Name of the allocator.
* @param[in] _p_pool Pool from which data will be allocated.
*/
#define NRF_BALLOC_INTERFACE_DEF(_type, _name, _p_pool) \
NRF_BALLOC_INTERFACE_CUSTOM_DEF(/* empty */, _type, _name, _p_pool)
/**@brief Define a local block allocator interface.
*
* @param[in] _type Type which is allocated.
* @param[in] _name Name of the allocator.
* @param[in] _p_pool Pool from which data will be allocated.
*/
#define NRF_BALLOC_INTERFACE_LOCAL_DEF(_type, _name, _p_pool) \
NRF_BALLOC_INTERFACE_CUSTOM_DEF(static, _type, _name, _p_pool)
/**@brief Function for initializing a block memory allocator pool.
*
* @param[out] p_pool Pointer to the pool that is to be initialized.
*
* @return NRF_SUCCESS on success, otherwise error code.
*/
ret_code_t nrf_balloc_init(nrf_balloc_t const * p_pool);
/**@brief Function for allocating an element from the pool.
*
* @note This module guarantees that the returned memory is aligned to 4.
*
* @param[in] p_pool Pointer to the memory pool from which the element will be allocated.
*
* @return Allocated element or NULL if the specified pool is empty.
*/
void * nrf_balloc_alloc(nrf_balloc_t const * p_pool);
/**@brief Function for freeing an element back to the pool.
*
* @param[in] p_pool Pointer to the memory pool.
* @param[in] p_element Element to be freed.
*/
void nrf_balloc_free(nrf_balloc_t const * p_pool, void * p_element);
/**@brief Function for getting maximum memory pool utilization.
*
* @param[in] p_pool Pointer to the memory pool instance.
*
* @return Maximum number of elements allocated from the pool.
*/
__STATIC_INLINE uint8_t nrf_balloc_max_utilization_get(nrf_balloc_t const * p_pool);
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE uint8_t nrf_balloc_max_utilization_get(nrf_balloc_t const * p_pool)
{
ASSERT(p_pool != NULL);
return p_pool->p_cb->max_utilization;
}
#endif //SUPPRESS_INLINE_IMPLEMENTATION
/**@brief Function for getting current memory pool utilization.
*
* @param[in] p_pool Pointer to the memory pool instance.
*
* @return Maximum number of elements allocated from the pool.
*/
__STATIC_INLINE uint8_t nrf_balloc_utilization_get(nrf_balloc_t const * p_pool);
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE uint8_t nrf_balloc_utilization_get(nrf_balloc_t const * p_pool)
{
ASSERT(p_pool != NULL);
return (p_pool->p_stack_limit - p_pool->p_cb->p_stack_pointer);
}
#endif //SUPPRESS_INLINE_IMPLEMENTATION
#ifdef __cplusplus
}
#endif
#endif // NRF_BALLOC_H__
/** @} */

View File

@ -0,0 +1,80 @@
/**
* Copyright (c) 2011 - 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 _NRF_DELAY_H
#define _NRF_DELAY_H
#include <nrfx.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Function for delaying execution for a number of microseconds.
*
* @param us_time Number of microseconds to wait.
*/
#define nrf_delay_us(us_time) NRFX_DELAY_US(us_time)
/**
* @brief Function for delaying execution for a number of milliseconds.
*
* @param ms_time Number of milliseconds to wait.
*/
__STATIC_INLINE void nrf_delay_ms(uint32_t ms_time)
{
if (ms_time == 0)
{
return;
}
do {
nrf_delay_us(1000);
} while (--ms_time);
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,291 @@
/**
* 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_log Logger module
* @{
* @ingroup app_common
*
* @brief The nrf_log module interface.
*/
#ifndef NRF_LOG_H_
#define NRF_LOG_H_
#include "sdk_common.h"
#include "nrf_section.h"
#if NRF_MODULE_ENABLED(NRF_LOG)
#include "nrf_strerror.h"
#define NRF_LOG_ERROR_STRING_GET(code) nrf_strerror_get(code)
#else
#define NRF_LOG_ERROR_STRING_GET(code) ""
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Severity level for the module.
*
* The severity level can be defined in a module to override the default.
*/
#ifndef NRF_LOG_LEVEL
#define NRF_LOG_LEVEL NRF_LOG_DEFAULT_LEVEL
#endif
/** @brief Initial severity if filtering is enabled.
*/
#ifndef NRF_LOG_INITIAL_LEVEL
#define NRF_LOG_INITIAL_LEVEL NRF_LOG_LEVEL
#endif
#include "nrf_log_internal.h"
/** @def NRF_LOG_ERROR
* @brief Macro for logging error messages. It takes a printf-like, formatted
* string with up to seven arguments.
*
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs.
*/
/** @def NRF_LOG_WARNING
* @brief Macro for logging error messages. It takes a printf-like, formatted
* string with up to seven arguments.
*
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes warning logs.
*/
/** @def NRF_LOG_INFO
* @brief Macro for logging error messages. It takes a printf-like, formatted
* string with up to seven arguments.
*
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes info logs.
*/
/** @def NRF_LOG_DEBUG
* @brief Macro for logging error messages. It takes a printf-like, formatted
* string with up to seven arguments.
*
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes debug logs.
*/
#define NRF_LOG_ERROR(...) NRF_LOG_INTERNAL_ERROR(__VA_ARGS__)
#define NRF_LOG_WARNING(...) NRF_LOG_INTERNAL_WARNING( __VA_ARGS__)
#define NRF_LOG_INFO(...) NRF_LOG_INTERNAL_INFO( __VA_ARGS__)
#define NRF_LOG_DEBUG(...) NRF_LOG_INTERNAL_DEBUG( __VA_ARGS__)
/** @def NRF_LOG_INST_ERROR
* @brief Macro for logging error messages for a given module instance. It takes a printf-like, formatted
* string with up to seven arguments.
*
* @param p_inst Pointer to the instance with logging support.
*
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs.
*/
/** @def NRF_LOG_INST_WARNING
* @brief Macro for logging error messages for a given module instance. It takes a printf-like, formatted
* string with up to seven arguments.
*
* @param p_inst Pointer to the instance with logging support.
*
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs.
*/
/** @def NRF_LOG_INST_INFO
* @brief Macro for logging error messages for a given module instance. It takes a printf-like, formatted
* string with up to seven arguments.
*
* @param p_inst Pointer to the instance with logging support.
*
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs.
*/
/** @def NRF_LOG_INST_DEBUG
* @brief Macro for logging error messages for given module instance. It takes a printf-like, formatted
* string with up to seven arguments.
*
* @param p_inst Pointer to the instance with logging support.
*
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs.
*/
#define NRF_LOG_INST_ERROR(p_inst,...) NRF_LOG_INTERNAL_INST_ERROR(p_inst,__VA_ARGS__)
#define NRF_LOG_INST_WARNING(p_inst,...) NRF_LOG_INTERNAL_INST_WARNING(p_inst,__VA_ARGS__)
#define NRF_LOG_INST_INFO(p_inst,...) NRF_LOG_INTERNAL_INST_INFO(p_inst, __VA_ARGS__)
#define NRF_LOG_INST_DEBUG(p_inst,...) NRF_LOG_INTERNAL_INST_DEBUG(p_inst, __VA_ARGS__)
/**
* @brief Macro for logging a formatted string without any prefix or timestamp.
*/
#define NRF_LOG_RAW_INFO(...) NRF_LOG_INTERNAL_RAW_INFO( __VA_ARGS__)
/** @def NRF_LOG_HEXDUMP_ERROR
* @brief Macro for logging raw bytes.
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs.
*
* @param p_data Pointer to data.
* @param len Data length in bytes.
*/
/** @def NRF_LOG_HEXDUMP_WARNING
* @brief Macro for logging raw bytes.
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes warning logs.
*
* @param p_data Pointer to data.
* @param len Data length in bytes.
*/
/** @def NRF_LOG_HEXDUMP_INFO
* @brief Macro for logging raw bytes.
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes info logs.
*
* @param p_data Pointer to data.
* @param len Data length in bytes.
*/
/** @def NRF_LOG_HEXDUMP_DEBUG
* @brief Macro for logging raw bytes.
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes debug logs.
*
* @param p_data Pointer to data.
* @param len Data length in bytes.
*/
#define NRF_LOG_HEXDUMP_ERROR(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_ERROR(p_data, len)
#define NRF_LOG_HEXDUMP_WARNING(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_WARNING(p_data, len)
#define NRF_LOG_HEXDUMP_INFO(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INFO(p_data, len)
#define NRF_LOG_HEXDUMP_DEBUG(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_DEBUG(p_data, len)
/** @def NRF_LOG_HEXDUMP_INST_ERROR
* @brief Macro for logging raw bytes for a specific module instance.
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs.
*
* @param p_inst Pointer to the instance with logging support.
* @param p_data Pointer to data.
* @param len Data length in bytes.
*/
/** @def NRF_LOG_HEXDUMP_INST_WARNING
* @brief Macro for logging raw bytes for a specific module instance.
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs.
*
* @param p_inst Pointer to the instance with logging support.
* @param p_data Pointer to data.
* @param len Data length in bytes.
*/
/** @def NRF_LOG_HEXDUMP_INST_INFO
* @brief Macro for logging raw bytes for a specific module instance.
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs.
*
* @param p_inst Pointer to the instance with logging support.
* @param p_data Pointer to data.
* @param len Data length in bytes.
*/
/** @def NRF_LOG_HEXDUMP_INST_DEBUG
* @brief Macro for logging raw bytes for a specific module instance.
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs.
*
* @param p_inst Pointer to the instance with logging support.
* @param p_data Pointer to data.
* @param len Data length in bytes.
*/
#define NRF_LOG_HEXDUMP_INST_ERROR(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_ERROR(p_inst, p_data, len)
#define NRF_LOG_HEXDUMP_INST_WARNING(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_WARNING(p_inst, p_data, len)
#define NRF_LOG_HEXDUMP_INST_INFO(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_INFO(p_inst, p_data, len)
#define NRF_LOG_HEXDUMP_INST_DEBUG(p_inst, p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INST_DEBUG(p_inst, p_data, len)
/**
* @brief Macro for logging hexdump without any prefix or timestamp.
*/
#define NRF_LOG_RAW_HEXDUMP_INFO(p_data, len) NRF_LOG_INTERNAL_RAW_HEXDUMP_INFO(p_data, len)
/**
* @brief Macro for copying a string to internal logger buffer if logs are deferred.
*
* @param _str String.
*/
#define NRF_LOG_PUSH(_str) NRF_LOG_INTERNAL_LOG_PUSH(_str)
/**
* @brief Function for copying a string to the internal logger buffer if logs are deferred.
*
* Use this function to store a string that is volatile (for example allocated
* on stack) or that may change before the deferred logs are processed. Such string is copied
* into the internal logger buffer and is persistent until the log is processed.
*
* @note If the logs are not deferred, then this function returns the input parameter.
*
* @param p_str Pointer to the user string.
*
* @return Address to the location where the string is stored in the internal logger buffer.
*/
uint32_t nrf_log_push(char * const p_str);
/**
* @brief Macro to be used in a formatted string to a pass float number to the log.
*
* Use this macro in a formatted string instead of the %f specifier together with
* @ref NRF_LOG_FLOAT macro.
* Example: NRF_LOG_INFO("My float number" NRF_LOG_FLOAT_MARKER "\r\n", NRF_LOG_FLOAT(f)))
*/
#define NRF_LOG_FLOAT_MARKER "%s%d.%02d"
/**
* @brief Macro for dissecting a float number into two numbers (integer and residuum).
*/
#define NRF_LOG_FLOAT(val) (uint32_t)(((val) < 0 && (val) > -1.0) ? "-" : ""), \
(int32_t)(val), \
(int32_t)((((val) > 0) ? (val) - (int32_t)(val) \
: (int32_t)(val) - (val))*100)
/**
* @brief Macro for registering an independent module.
*
* Registration creates set of dynamic (RAM) and constant variables associated with the module.
*/
#define NRF_LOG_MODULE_REGISTER() NRF_LOG_INTERNAL_MODULE_REGISTER()
#ifdef __cplusplus
}
#endif
#endif // NRF_LOG_H_
/** @} */

View File

@ -0,0 +1,129 @@
/**
* Copyright (c) 2018 - 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_log_backend_flash Flash logger backend
* @{
* @ingroup nrf_log
* @brief Flash logger backend.
*/
#ifndef NRF_LOG_BACKEND_FLASH_H
#define NRF_LOG_BACKEND_FLASH_H
#include "nrf_log_backend_interface.h"
#include "nrf_fstorage.h"
#include "nrf_log_internal.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Flashlog logger backend API. */
extern const nrf_log_backend_api_t nrf_log_backend_flashlog_api;
/** @brief Crashlog logger backend API. */
extern const nrf_log_backend_api_t nrf_log_backend_crashlog_api;
/** @brief Flashlog logger backend structure. */
typedef struct {
nrf_log_backend_t backend;
} nrf_log_backend_flashlog_t;
/** @brief Crashlog logger backend structure. */
typedef struct {
nrf_log_backend_t backend;
} nrf_log_backend_crashlog_t;
/** @brief Macro for creating an instance of the flashlog logger backend. */
#define NRF_LOG_BACKEND_FLASHLOG_DEF(name) \
static nrf_log_backend_flashlog_t name = { \
.backend = {.p_api = &nrf_log_backend_flashlog_api}, \
}
/** @brief Macro for creating an instance of the crashlog logger backend. */
#define NRF_LOG_BACKEND_CRASHLOG_DEF(name) \
static nrf_log_backend_crashlog_t name = { \
.backend = {.p_api = &nrf_log_backend_crashlog_api}, \
}
/**
* @brief Function for initializing the flash logger backend.
*
* Flash logger backend consists of two logical backends: flashlog and crashlog. Since both
* backends write to the same flash area, the initialization is common.
*
* @param p_fs_api fstorage API to be used.
*
* @return NRF_SUCCESS or error code returned by @ref nrf_fstorage_init.
*/
ret_code_t nrf_log_backend_flash_init(nrf_fstorage_api_t const * p_fs_api);
/**
* @brief Function for getting a log entry stored in flash.
*
* Log messages stored in flash can be read one by one starting from the oldest one.
*
* @param[in, out] p_token Token reused between consecutive readings of log entries.
* Token must be set to 0 to read the first entry.
* @param[out] pp_header Pointer to the entry header.
* @param[out] pp_data Pointer to the data part of the entry (arguments or data in case of hexdump).
*
* @retval NRF_SUCCESS Entry was successfully read.
* @retval NRF_ERROR_NOT_SUPPORTED fstorage API does not support direct reading.
* @retval NRF_ERROR_NOT_FOUND Entry not found. Last entry was already reached or area is empty.
*/
ret_code_t nrf_log_backend_flash_next_entry_get(uint32_t * p_token,
nrf_log_header_t * * pp_header,
uint8_t * * pp_data);
/**
* @brief Function for erasing flash area dedicated for the flash logger backend.
*/
ret_code_t nrf_log_backend_flash_erase(void);
#ifdef __cplusplus
}
#endif
#endif //NRF_LOG_BACKEND_UART_H
/** @} */

View File

@ -0,0 +1,220 @@
/**
* 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.
*
*/
#ifndef NRF_LOG_BACKEND_INTERFACE_H
#define NRF_LOG_BACKEND_INTERFACE_H
/**@file
* @addtogroup nrf_log Logger module
* @ingroup app_common
*
* @defgroup nrf_log_backend_interface Logger backend interface
* @{
* @ingroup nrf_log
* @brief The nrf_log backend interface.
*/
#include "nrf_memobj.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief nrf_log entry.
*/
typedef nrf_memobj_t nrf_log_entry_t;
/* Forward declaration of the nrf_log_backend_t type. */
typedef struct nrf_log_backend_s nrf_log_backend_t;
/**
* @brief Logger backend API.
*/
typedef struct
{
/**
* @brief @ref nrf_log_backend_put
*/
void (*put)(nrf_log_backend_t const * p_backend, nrf_log_entry_t * p_entry);
/**
* @brief @ref nrf_log_backend_panic_set
*/
void (*panic_set)(nrf_log_backend_t const * p_backend);
/**
* @brief @ref nrf_log_backend_flush
*/
void (*flush)(nrf_log_backend_t const * p_backend);
} nrf_log_backend_api_t;
/**
* @brief Logger backend structure.
*/
struct nrf_log_backend_s
{
nrf_log_backend_api_t const * p_api; //!< Pointer to interface.
nrf_log_backend_t * p_next; //!< Pointer to next backend added to the logger.
uint8_t id; //!< Backend id.
bool enabled;//!< Flag indicating backend status.
};
/**
* @brief Function for putting message with log entry to the backend.
*
* @param[in] p_backend Pointer to the backend instance.
* @param[in] p_msg Pointer to message with log entry.
*/
__STATIC_INLINE void nrf_log_backend_put(nrf_log_backend_t const * p_backend,
nrf_log_entry_t * p_msg);
/**
* @brief Function for reconfiguring backend to panic mode.
*
* @param[in] p_backend Pointer to the backend instance.
*/
__STATIC_INLINE void nrf_log_backend_panic_set(nrf_log_backend_t const * p_backend);
/**
* @brief Function for flushing backend.
*
* On flushing request backend should release log message(s).
*
* @param[in] p_backend Pointer to the backend instance.
*/
__STATIC_INLINE void nrf_log_backend_flush(nrf_log_backend_t const * p_backend);
/**
* @brief Function for setting backend id.
*
* @note It is used internally by the logger.
*
* @param[in] p_backend Pointer to the backend instance.
* @param[in] id Id.
*/
__STATIC_INLINE void nrf_log_backend_id_set(nrf_log_backend_t * p_backend, uint8_t id);
/**
* @brief Function for getting backend id.
*
* @note It is used internally by the logger.
*
* @param[in] p_backend Pointer to the backend instance.
* @return Id.
*/
__STATIC_INLINE uint8_t nrf_log_backend_id_get(nrf_log_backend_t const * p_backend);
/**
* @brief Function for enabling backend.
*
* @param[in] p_backend Pointer to the backend instance.
*/
__STATIC_INLINE void nrf_log_backend_enable(nrf_log_backend_t * p_backend);
/**
* @brief Function for disabling backend.
*
* @param[in] p_backend Pointer to the backend instance.
*/
__STATIC_INLINE void nrf_log_backend_disable(nrf_log_backend_t * p_backend);
/**
* @brief Function for checking state of the backend.
*
* @param[in] p_backend Pointer to the backend instance.
*
* @return True if backend is enabled, false otherwise.
*/
__STATIC_INLINE bool nrf_log_backend_is_enabled(nrf_log_backend_t const * p_backend);
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE void nrf_log_backend_put(nrf_log_backend_t const * p_backend,
nrf_log_entry_t * p_msg)
{
p_backend->p_api->put(p_backend, p_msg);
}
__STATIC_INLINE void nrf_log_backend_panic_set(nrf_log_backend_t const * p_backend)
{
p_backend->p_api->panic_set(p_backend);
}
__STATIC_INLINE void nrf_log_backend_flush(nrf_log_backend_t const * p_backend)
{
p_backend->p_api->flush(p_backend);
}
__STATIC_INLINE void nrf_log_backend_id_set(nrf_log_backend_t * p_backend, uint8_t id)
{
p_backend->id = id;
}
__STATIC_INLINE uint8_t nrf_log_backend_id_get(nrf_log_backend_t const * p_backend)
{
return p_backend->id;
}
__STATIC_INLINE void nrf_log_backend_enable(nrf_log_backend_t * p_backend)
{
p_backend->enabled = true;
}
__STATIC_INLINE void nrf_log_backend_disable(nrf_log_backend_t * p_backend)
{
p_backend->enabled = false;
}
__STATIC_INLINE bool nrf_log_backend_is_enabled(nrf_log_backend_t const * p_backend)
{
return p_backend->enabled;
}
#endif // SUPPRESS_INLINE_IMPLEMENTATION
#ifdef __cplusplus
}
#endif
#endif //NRF_LOG_BACKEND_INTERFACE_H
/** @} */

View File

@ -0,0 +1,82 @@
/**
* 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_log_backend_rtt Log RTT backend
* @{
* @ingroup nrf_log
* @brief Log RTT backend.
*/
#ifndef NRF_LOG_BACKEND_RTT_H
#define NRF_LOG_BACKEND_RTT_H
#include "nrf_log_backend_interface.h"
#ifdef __cplusplus
extern "C" {
#endif
extern const nrf_log_backend_api_t nrf_log_backend_rtt_api;
typedef struct {
nrf_log_backend_t backend;
} nrf_log_backend_rtt_t;
/**
* @brief RTT backend definition
*
* @param _name Name of the instance.
*/
#define NRF_LOG_BACKEND_RTT_DEF(_name) \
static nrf_log_backend_rtt_t _name = { \
.backend = {.p_api = &nrf_log_backend_rtt_api}, \
}
void nrf_log_backend_rtt_init(void);
#ifdef __cplusplus
}
#endif
#endif //NRF_LOG_BACKEND_RTT_H
/** @} */

View File

@ -0,0 +1,77 @@
/**
* 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_log_backend_uart Log UART backend
* @{
* @ingroup nrf_log
* @brief Log UART backend.
*/
#ifndef NRF_LOG_BACKEND_UART_H
#define NRF_LOG_BACKEND_UART_H
#include "nrf_log_backend_interface.h"
#ifdef __cplusplus
extern "C" {
#endif
extern const nrf_log_backend_api_t nrf_log_backend_uart_api;
typedef struct {
nrf_log_backend_t backend;
} nrf_log_backend_uart_t;
#define NRF_LOG_BACKEND_UART_DEF(name) \
static nrf_log_backend_uart_t name = { \
.backend = {.p_api = &nrf_log_backend_uart_api}, \
}
void nrf_log_backend_uart_init(void);
#ifdef __cplusplus
}
#endif
#endif //NRF_LOG_BACKEND_UART_H
/** @} */

View File

@ -0,0 +1,226 @@
/**
* 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.
*
*/
#ifndef NRF_LOG_CTRL_H
#define NRF_LOG_CTRL_H
/**@file
* @addtogroup nrf_log Logger module
* @ingroup app_common
*
* @defgroup nrf_log_ctrl Functions for controlling nrf_log
* @{
* @ingroup nrf_log
* @brief The nrf_log control interface.
*/
#include "sdk_config.h"
#include "sdk_errors.h"
#include <stdint.h>
#include <stdbool.h>
#include "nrf_log_types.h"
#include "nrf_log_ctrl_internal.h"
#include "nrf_log_backend_interface.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Timestamp function prototype.
*
* @return Timestamp value.
*/
typedef uint32_t (*nrf_log_timestamp_func_t)(void);
/**@brief Macro for initializing the logs.
*
* Macro has one or two parameters. First parameter (obligatory) is the timestamp function (@ref nrf_log_timestamp_func_t).
* Additionally, as the second parameter timestamp frequency in Hz can be provided. If not provided then default
* frequency is used (@ref NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY). Frequency is used to format timestamp prefix if
* @ref NRF_LOG_STR_FORMATTER_TIMESTAMP_FORMAT_ENABLED is set.
*
* @return NRF_SUCCESS after successful initialization, otherwise an error code.
*/
#define NRF_LOG_INIT(...) NRF_LOG_INTERNAL_INIT(__VA_ARGS__)
/**@brief Macro for processing a single log entry from a queue of deferred logs.
*
* You can call this macro from the main context or from the error handler to process
* log entries one by one.
*
* @note If logs are not deferred, this call has no use and is defined as 'false'.
*
* @retval true There are more logs to process in the buffer.
* @retval false No more logs in the buffer.
*/
#define NRF_LOG_PROCESS() NRF_LOG_INTERNAL_PROCESS()
/** @brief Macro for processing all log entries from the buffer.
* It blocks until all buffered entries are processed by the backend.
*
* @note If logs are not deferred, this call has no use and is empty.
*/
#define NRF_LOG_FLUSH() NRF_LOG_INTERNAL_FLUSH()
/** @brief Macro for flushing log data before reset.
*
* @note If logs are not deferred, this call has no use and is empty.
*
* @note If RTT is used, then a breakpoint is hit once flushed.
*/
#define NRF_LOG_FINAL_FLUSH() NRF_LOG_INTERNAL_FINAL_FLUSH()
/**
* @brief Function for initializing the frontend and the default backend.
*
* @ref NRF_LOG_INIT calls this function to initialize the frontend and the backend.
* If custom backend is used, then @ref NRF_LOG_INIT should not be called.
* Instead, frontend and user backend should be verbosely initialized.
*
* @param timestamp_func Function for getting a 32-bit timestamp.
* @param timestamp_freq Frequency of the timestamp.
*
* @return Error status.
*
*/
ret_code_t nrf_log_init(nrf_log_timestamp_func_t timestamp_func, uint32_t timestamp_freq);
/**
* @brief Function for adding new backend interface to the logger.
*
* @param p_backend Pointer to the backend interface.
* @param severity Initial value of severity level for each module forwarded to the backend. This
* option is only applicable if @ref NRF_LOG_FILTERS_ENABLED is set.
* @return -1 if backend cannot be added or positive number (backend ID).
*/
int32_t nrf_log_backend_add(nrf_log_backend_t * p_backend, nrf_log_severity_t severity);
/**
* @brief Function for removing backend from the logger.
*
* @param p_backend Pointer to the backend interface.
*
*/
void nrf_log_backend_remove(nrf_log_backend_t * p_backend);
/**
* @brief Function for setting logger backends into panic mode.
*
* When this function is called all attached backends are informed about panic state of the system.
* It is up to the backend to react properly (hold or process logs in blocking mode, etc.)
*/
void nrf_log_panic(void);
/**
* @brief Function for handling a single log entry.
*
* Use this function only if the logs are buffered. It takes a single entry from the
* buffer and attempts to process it.
*
* @retval true If there are more entries to process.
* @retval false If there are no more entries to process.
*/
bool nrf_log_frontend_dequeue(void);
/**
* @brief Function for getting number of independent log modules registered into the logger.
*
* @return Number of registered modules.
*/
uint32_t nrf_log_module_cnt_get(void);
/**
* @brief Function for getting module name.
*
* @param module_id Module ID.
* @param is_ordered_idx Module ID is given is index in alphabetically sorted list of modules.
* @return Pointer to string with module name.
*/
const char * nrf_log_module_name_get(uint32_t module_id, bool is_ordered_idx);
/**
* @brief Function for getting coloring of specific logs.
*
* @param module_id Module ID.
* @param severity Log severity.
*
* @return ID of the color.
*/
uint8_t nrf_log_color_id_get(uint32_t module_id, nrf_log_severity_t severity);
/**
* @brief Function for configuring filtering ofs logs in the module.
*
* Filtering of logs in modules is independent for each backend.
*
* @param backend_id Backend ID which want to chenge its configuration.
* @param module_id Module ID which logs will be reconfigured.
* @param severity New severity filter.
*/
void nrf_log_module_filter_set(uint32_t backend_id,
uint32_t module_id,
nrf_log_severity_t severity);
/**
* @brief Function for getting module severity level.
*
* @param backend_id Backend ID.
* @param module_id Module ID.
* @param is_ordered_idx Module ID is given is index in alphabetically sorted list of modules.
* @param dynamic It true current filter for given backend is returned. If false then
* compiled-in level is returned (maximum available). If this parameter is
* false then backend_id parameter is not used.
*
* @return Severity.
*/
nrf_log_severity_t nrf_log_module_filter_get(uint32_t backend_id,
uint32_t module_id,
bool is_ordered_idx,
bool dynamic);
#ifdef __cplusplus
}
#endif
#endif // NRF_LOG_CTRL_H
/**
*@}
**/

View File

@ -0,0 +1,81 @@
/**
* 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.
*
*/
#ifndef NRF_LOG_DEFAULT_BACKENDS_H__
#define NRF_LOG_DEFAULT_BACKENDS_H__
/**@file
* @addtogroup nrf_log Logger module
* @ingroup app_common
*
* @defgroup nrf_log_default_backends Functions for initializing and adding default backends
* @{
* @ingroup nrf_log
* @brief The nrf_log default backends.
*/
#include "sdk_config.h"
#include "sdk_errors.h"
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @def NRF_LOG_DEFAULT_BACKENDS_INIT
* @brief Macro for initializing default backends.
*
* Each backend enabled in configuration is initialized and added as a backend to the logger.
*/
#if NRF_LOG_ENABLED
#define NRF_LOG_DEFAULT_BACKENDS_INIT() nrf_log_default_backends_init()
#else
#define NRF_LOG_DEFAULT_BACKENDS_INIT()
#endif
void nrf_log_default_backends_init(void);
#ifdef __cplusplus
}
#endif
/** @} */
#endif // NRF_LOG_DEFAULT_BACKENDS_H__

View File

@ -0,0 +1,135 @@
/**
* Copyright (c) 2018 - 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 NRF_LOG_INSTANCE_H
#define NRF_LOG_INSTANCE_H
#include "sdk_config.h"
#include "nrf_section.h"
#include "nrf_log_types.h"
#include <stdint.h>
/*
* For GCC, sections are sorted in the group by the linker. For IAR and KEIL, it is assumed that linker will sort
* dynamic and const section in the same order (but in different locations). Proper message formatting
* is based on that assumption.
*/
#if defined(__GNUC__)
#define NRF_LOG_DYNAMIC_SECTION_NAME(_module_name) CONCAT_2(log_dynamic_data_,_module_name)
#define NRF_LOG_CONST_SECTION_NAME(_module_name) CONCAT_2(log_const_data_,_module_name)
#else
#define NRF_LOG_DYNAMIC_SECTION_NAME(_module_name) log_dynamic_data
#define NRF_LOG_CONST_SECTION_NAME(_module_name) log_const_data
#endif
#define NRF_LOG_ITEM_DATA(_name) CONCAT_3(m_nrf_log_,_name,_logs_data)
#define NRF_LOG_ITEM_DATA_DYNAMIC(_name) CONCAT_2(NRF_LOG_ITEM_DATA(_name),_dynamic)
#define NRF_LOG_ITEM_DATA_CONST(_name) CONCAT_2(NRF_LOG_ITEM_DATA(_name),_const)
#ifdef UNIT_TEST
#define _CONST
#else
#define _CONST const
#endif
#if NRF_LOG_FILTERS_ENABLED
#define NRF_LOG_DYNAMIC_STRUCT_NAME nrf_log_module_dynamic_data_t
#else
#define NRF_LOG_DYNAMIC_STRUCT_NAME nrf_log_module_reduced_dynamic_data_t
#endif
#define NRF_LOG_INTERNAL_ITEM_REGISTER( \
_name, _str_name, _info_color, _debug_color, _initial_lvl, _compiled_lvl) \
NRF_SECTION_ITEM_REGISTER(NRF_LOG_CONST_SECTION_NAME(_name), \
_CONST nrf_log_module_const_data_t NRF_LOG_ITEM_DATA_CONST(_name)) = { \
.p_module_name = _str_name, \
.info_color_id = (_info_color), \
.debug_color_id = (_debug_color), \
.compiled_lvl = (nrf_log_severity_t)(_compiled_lvl), \
.initial_lvl = (nrf_log_severity_t)(_initial_lvl), \
}; \
NRF_SECTION_ITEM_REGISTER(NRF_LOG_DYNAMIC_SECTION_NAME(_name), \
NRF_LOG_DYNAMIC_STRUCT_NAME NRF_LOG_ITEM_DATA_DYNAMIC(_name))
/**@file
*
* @defgroup nrf_log_instance Macros for logging on instance level
* @{
* @ingroup nrf_log
*
* @brief Macros for logging on instance level
*/
/** @def NRF_LOG_INSTANCE_PTR_DECLARE
* @brief Macro for declaring a logger instance pointer in the module stucture.
*/
/** @def NRF_LOG_INSTANCE_REGISTER
* @brief Macro for creating an independent module instance.
*
* Module instance provides filtering of logs on instance level instead of module level.
*/
/** @def NRF_LOG_INSTANCE_PTR_INIT
* @brief Macro for initializing a pointer to the logger instance.
*/
/** @} */
#if NRF_LOG_ENABLED
#define NRF_LOG_INSTANCE_PTR_DECLARE(_p_name) NRF_LOG_DYNAMIC_STRUCT_NAME * _p_name;
#define NRF_LOG_INSTANCE_REGISTER( \
_module_name, _inst_name, _info_color, _debug_color, _initial_lvl, _compiled_lvl) \
NRF_LOG_INTERNAL_ITEM_REGISTER(CONCAT_3(_module_name,_,_inst_name), \
STRINGIFY(_module_name._inst_name), \
_info_color, \
_debug_color, \
_initial_lvl, \
_compiled_lvl)
#define NRF_LOG_INSTANCE_PTR_INIT(_p_name, _module_name, _inst_name) \
._p_name = &NRF_LOG_ITEM_DATA_DYNAMIC(CONCAT_3(_module_name,_,_inst_name)),
#else
#define NRF_LOG_INSTANCE_PTR_DECLARE(_p_name)
#define NRF_LOG_INSTANCE_REGISTER(_module_name, _inst_name, info_color, debug_color, _initial_lvl, compiled_lvl)
#define NRF_LOG_INSTANCE_PTR_INIT(_p_name, _module_name, _inst_name)
#endif
#endif //NRF_LOG_INSTANCE_H

View File

@ -0,0 +1,86 @@
/**
* 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_log_str_formatter String formatter for the logger messages
* @{
* @ingroup nrf_log
*/
#ifndef NRF_LOG_STR_FORMATTER_H
#define NRF_LOG_STR_FORMATTER_H
#include <stdint.h>
#include "nrf_fprintf.h"
#include "nrf_log_ctrl.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct
{
uint32_t timestamp;
uint16_t module_id;
uint16_t dropped;
nrf_log_severity_t severity;
uint8_t use_colors;
} nrf_log_str_formatter_entry_params_t;
void nrf_log_std_entry_process(char const * p_str,
uint32_t const * p_args,
uint32_t nargs,
nrf_log_str_formatter_entry_params_t * p_params,
nrf_fprintf_ctx_t * p_ctx);
void nrf_log_hexdump_entry_process(uint8_t * p_data,
uint32_t data_len,
nrf_log_str_formatter_entry_params_t * p_params,
nrf_fprintf_ctx_t * p_ctx);
void nrf_log_str_formatter_timestamp_freq_set(uint32_t freq);
#ifdef __cplusplus
}
#endif
#endif //NRF_LOG_STR_FORMATTER_H
/** @} */

View File

@ -0,0 +1,97 @@
/**
* Copyright (c) 2018 - 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 NRF_LOG_TYPES_H
#define NRF_LOG_TYPES_H
#include <stdint.h>
/**
* @brief Logger severity levels.
*/
typedef enum
{
NRF_LOG_SEVERITY_NONE,
NRF_LOG_SEVERITY_ERROR,
NRF_LOG_SEVERITY_WARNING,
NRF_LOG_SEVERITY_INFO,
NRF_LOG_SEVERITY_DEBUG,
NRF_LOG_SEVERITY_INFO_RAW, /* Artificial level to pass information about skipping string postprocessing.*/
} nrf_log_severity_t;
/**
* @brief Structure holding dynamic data associated with a module or instance if filtering is enabled (@ref NRF_LOG_FILTERS_ENABLED).
*
* See @ref NRF_LOG_MODULE_REGISTER and @ref NRF_LOG_INSTANCE_REGISTER.
*/
typedef struct
{
uint16_t module_id; ///< Module ID assigned during initialization.
uint16_t order_idx; ///< Ordered index of the module (used for auto-completion).
uint32_t filter; ///< Current highest severity level accepted (redundant to @ref nrf_log_module_dynamic_data_t::filter_lvls, used for optimization)
uint32_t filter_lvls; ///< Current severity levels for each backend (3 bits per backend).
} nrf_log_module_dynamic_data_t;
/**
* @brief Structure holding dynamic data associated with a module or instance if filtering is disabled (@ref NRF_LOG_FILTERS_ENABLED).
*
* See @ref NRF_LOG_MODULE_REGISTER and @ref NRF_LOG_INSTANCE_REGISTER.
*/
typedef struct
{
uint16_t module_id; ///< Module ID assigned during initialization.
uint16_t padding; ///< Padding to fit in word.
} nrf_log_module_reduced_dynamic_data_t;
/**
* @brief Structure holding constant data associated with a module or instance.
*
* See @ref NRF_LOG_MODULE_REGISTER and @ref NRF_LOG_INSTANCE_REGISTER.
*/
typedef struct
{
const char * p_module_name; ///< Module or instance name.
uint8_t info_color_id; ///< Color code of info messages.
uint8_t debug_color_id; ///< Color code of debug messages.
nrf_log_severity_t compiled_lvl; ///< Compiled highest severity level.
nrf_log_severity_t initial_lvl; ///< Severity level for given module or instance set on backend initialization.
} nrf_log_module_const_data_t;
#endif //NRF_LOG_TYPES_H

View File

@ -0,0 +1,739 @@
/**
* 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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_FLASH)
#include "nrf_log_backend_flash.h"
#include "nrf_log_str_formatter.h"
#include "nrf_fstorage_nvmc.h"
#include "nrf_log.h"
#include "nrf_atomic.h"
#include "nrf_queue.h"
#include "app_error.h"
#include <stdbool.h>
#if (NRF_LOG_BACKEND_FLASHLOG_ENABLED == 0) && (NRF_LOG_BACKEND_CRASHLOG_ENABLED == 0)
#error "No flash backend enabled."
#endif
/** @brief Maximum logger message payload (arguments or data in hexdump) which can be stored. */
#define FLASH_LOG_MAX_PAYLOAD_SIZE (NRF_LOG_BACKEND_FLASH_SER_BUFFER_SIZE - sizeof(nrf_log_header_t))
/** @brief Size of serialization buffer in words. */
#define FLASH_LOG_SER_BUFFER_WORDS (NRF_LOG_BACKEND_FLASH_SER_BUFFER_SIZE/sizeof(uint32_t))
/** @brief Length of logger header. */
#define LOG_HEADER_LEN (sizeof(nrf_log_header_t))
/** @brief Length of logger header given in 32 bit words. */
#define LOG_HEADER_LEN_WORDS (LOG_HEADER_LEN/sizeof(uint32_t))
/** @brief Maximum possible length of standard log message. */
#define STD_LOG_MSG_MAX_LEN (LOG_HEADER_LEN + NRF_LOG_MAX_NUM_OF_ARGS*sizeof(uint32_t))
/* Buffer must be multiple of 4. */
STATIC_ASSERT((NRF_LOG_BACKEND_FLASH_SER_BUFFER_SIZE % sizeof(uint32_t)) == 0);
/* Buffer must fit standard log message. */
STATIC_ASSERT(NRF_LOG_BACKEND_FLASH_SER_BUFFER_SIZE >= STD_LOG_MSG_MAX_LEN);
/** @brief Flash page size in bytes. */
#define CODE_PAGE_SIZE 4096
/** @brief Start address of the area dedicated for flash log. */
#define FLASH_LOG_START_ADDR (NRF_LOG_BACKEND_FLASH_START_PAGE * CODE_PAGE_SIZE)
/** @brief End address of the area dedicated for flash log. */
#define FLASH_LOG_END_ADDR (FLASH_LOG_START_ADDR + (NRF_LOG_BACKEND_PAGES * CODE_PAGE_SIZE) - 1)
/** @brief Size of the area dedicated for flash log. */
#define FLASH_LOG_SIZE (NRF_LOG_BACKEND_PAGES * CODE_PAGE_SIZE)
/** @brief Start address determined in runtime.
*
* If configuration indicates that flash log should be placed after application.
* */
#if defined ( __CC_ARM )
#define RUNTIME_START_ADDR \
_Pragma("diag_suppress 170") \
((NRF_LOG_BACKEND_FLASH_START_PAGE == 0) ? \
(CODE_PAGE_SIZE*CEIL_DIV((uint32_t)CODE_END, CODE_PAGE_SIZE)) : FLASH_LOG_START_ADDR) \
_Pragma("diag_default 170")
#else
#define RUNTIME_START_ADDR ((NRF_LOG_BACKEND_FLASH_START_PAGE == 0) ? \
(CODE_PAGE_SIZE*CEIL_DIV((uint32_t)CODE_END, CODE_PAGE_SIZE)) : FLASH_LOG_START_ADDR)
#endif
static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt);
/** @brief Message queue for run time flash log. */
#if NRF_LOG_BACKEND_FLASHLOG_ENABLED
NRF_QUEUE_DEF(nrf_log_entry_t *,
m_flashlog_queue,
NRF_LOG_BACKEND_FLASHLOG_QUEUE_SIZE,
NRF_QUEUE_MODE_NO_OVERFLOW);
static const nrf_queue_t * mp_flashlog_queue = &m_flashlog_queue;
#else
static const nrf_queue_t * mp_flashlog_queue = NULL;
#endif
/** @brief Message FIFO for crash log. */
#if NRF_LOG_BACKEND_CRASHLOG_ENABLED
NRF_QUEUE_DEF(nrf_log_entry_t *,
m_crashlog_queue,
NRF_LOG_BACKEND_CRASHLOG_FIFO_SIZE,
NRF_QUEUE_MODE_NO_OVERFLOW);
static const nrf_queue_t * mp_crashlog_queue = &m_crashlog_queue;
#else
static const nrf_queue_t * mp_crashlog_queue = NULL;
#endif
/** @brief Fstorage instance used for flash log. */
NRF_FSTORAGE_DEF(nrf_fstorage_t m_log_flash_fstorage) =
{
/* Set a handler for fstorage events. */
.evt_handler = fstorage_evt_handler,
.start_addr = FLASH_LOG_START_ADDR,
.end_addr = FLASH_LOG_END_ADDR,
};
/** @brief Flash log state. */
typedef enum
{
LOG_BACKEND_FLASH_ACTIVE, /**< Flash backend is active. */
LOG_BACKEND_FLASH_INACTIVE, /**< Flash backend is inactive. All incoming requests are skipped. */
LOG_BACKEND_FLASH_IN_PANIC, /**< Flash backend is in panic mode. Incoming messages are written to flash in synchronous mode. */
} log_backend_flash_state_t;
static log_backend_flash_state_t m_state; /**< Flash logger backend state. */
static nrf_atomic_flag_t m_busy_flag; /**< Flag indicating if module performs flash writing. */
static uint32_t m_flash_buf[FLASH_LOG_SER_BUFFER_WORDS]; /**< Buffer used for serializing messages. */
static uint32_t m_curr_addr; /**< Address of free spot in the storage area. */
static size_t m_curr_len; /**< Length of current message being written. */
static uint32_t m_dropped; /**< Number of dropped messages. */
/** @brief Log message string injected when entering panic mode. */
static const char crashlog_str[] = "-----------CRASHLOG------------\r\n";
/** @brief Function saturates input to maximum possible length and rounds up value to be multiple
* of word size.
*
* @param length Length value.
*
* @return Modified input length.
*/
static uint32_t saturate_align_length(uint32_t length)
{
length = (length > FLASH_LOG_MAX_PAYLOAD_SIZE) ? FLASH_LOG_MAX_PAYLOAD_SIZE : length; //saturate
length = CEIL_DIV(length, sizeof(uint32_t))*sizeof(uint32_t);
return length;
}
/**
* @brief Function for copying logger message to the buffer.
*
* @param[in] p_msg Logger message.
* @param[out] p_buf Output buffer where serialized message is placed.
* @param[in,out] p_len Buffer size as input, length of prepared data as output.
*
* @return True if message fits into the buffer, false otherwise
*/
static bool msg_to_buf(nrf_log_entry_t * p_msg, uint8_t * p_buf, size_t * p_len)
{
uint32_t data_len;
nrf_log_header_t header = {0};
uint32_t memobj_offset = HEADER_SIZE*sizeof(uint32_t);
nrf_memobj_read(p_msg, &header, HEADER_SIZE*sizeof(uint32_t), 0);
memcpy(p_buf, &header, sizeof(nrf_log_header_t));
p_buf += sizeof(nrf_log_header_t);
switch (header.base.generic.type)
{
case HEADER_TYPE_STD:
{
data_len = header.base.std.nargs * sizeof(uint32_t);
break;
}
case HEADER_TYPE_HEXDUMP:
{
data_len = saturate_align_length(header.base.hexdump.len);
break;
}
default:
*p_len = 0;
return false;
}
nrf_memobj_read(p_msg, p_buf, data_len, memobj_offset);
if (*p_len >= sizeof(nrf_log_header_t) + data_len)
{
*p_len = sizeof(nrf_log_header_t) + data_len;
return true;
}
else
{
return false;
}
}
/**
* @brief Function for getting logger message stored in flash.
*
* @param[in] p_buf Pointer to the location where message is stored.
* @param[out] pp_header Pointer to the log message header.
* @param[out] pp_data Pointer to the log message data (arguments or data in case of hexdump).
*
* @return True if message was successfully fetched, false otherwise.
*/
static bool msg_from_buf(uint32_t * p_buf,
nrf_log_header_t * * pp_header,
uint8_t * * pp_data,
uint32_t * p_len)
{
*pp_header = (nrf_log_header_t *)p_buf;
*pp_data = (uint8_t *)&p_buf[LOG_HEADER_LEN_WORDS];
uint32_t data_len;
switch ((*pp_header)->base.generic.type)
{
case HEADER_TYPE_STD:
{
data_len = ((*pp_header)->base.std.nargs)*sizeof(uint32_t);
break;
}
case HEADER_TYPE_HEXDUMP:
{
data_len = saturate_align_length((*pp_header)->base.hexdump.len);
break;
}
default:
return false;
}
*p_len = LOG_HEADER_LEN + data_len;
return true;
}
/**
* @brief Function for processing log message queue.
*
* If writing to flash is synchronous then function drains the queue and writes all messages to flash.
* If writing to flash is asynchronous then function starts single write operation. In asynchronous mode
* function is called when new message is put into the queue from from flash operation callback.
*
* Function detects the situation that flash module reports attempt to write outside dedicated area.
* In that case flash backend stops writing any new messages.
*
* @param p_queue Queue will log messages
* @param fstorage_blocking If true it indicates that flash operations are blocking, event handler is not used.
*/
static void log_msg_queue_process(nrf_queue_t const * p_queue, bool fstorage_blocking)
{
nrf_log_entry_t * p_msg;
bool busy = false;
while (nrf_queue_pop(p_queue, &p_msg) == NRF_SUCCESS)
{
ret_code_t err_code;
m_curr_len = sizeof(m_flash_buf);
if (!msg_to_buf(p_msg, (uint8_t *)m_flash_buf, &m_curr_len))
{
continue;
}
err_code = nrf_fstorage_write(&m_log_flash_fstorage, m_curr_addr, m_flash_buf, m_curr_len, p_msg);
if (err_code == NRF_SUCCESS)
{
if (fstorage_blocking)
{
m_curr_addr += m_curr_len;
nrf_memobj_put(p_msg);
}
else
{
busy = true;
break;
}
}
else if (!fstorage_blocking && (err_code == NRF_ERROR_NO_MEM))
{
// fstorage queue got full. Drop entry.
nrf_memobj_put(p_msg);
m_dropped++;
break;
}
else if (err_code == NRF_ERROR_INVALID_ADDR)
{
// Trying to write outside the area, flash log is full. Skip any new writes.
nrf_memobj_put(p_msg);
m_state = LOG_BACKEND_FLASH_INACTIVE;
}
else
{
ASSERT(false);
}
}
if (!busy)
{
UNUSED_RETURN_VALUE(nrf_atomic_flag_clear(&m_busy_flag));
}
}
static void queue_element_drop(nrf_queue_t const * p_queue)
{
nrf_log_entry_t * p_msg;
if (nrf_queue_pop(p_queue, &p_msg) == NRF_SUCCESS)
{
m_dropped++;
nrf_memobj_put(p_msg);
}
}
static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt)
{
if (m_state == LOG_BACKEND_FLASH_ACTIVE)
{
switch (p_evt->id)
{
case NRF_FSTORAGE_EVT_WRITE_RESULT:
{
if (p_evt->result == NRF_SUCCESS)
{
m_curr_addr += m_curr_len;
m_curr_len = 0;
log_msg_queue_process(mp_flashlog_queue, false);
}
else
{
m_dropped++;
}
if (p_evt->p_param)
{
nrf_memobj_put((nrf_log_entry_t *)p_evt->p_param);
}
break;
}
default:
break;
}
}
else if ((m_state == LOG_BACKEND_FLASH_INACTIVE) &&
(p_evt->id == NRF_FSTORAGE_EVT_ERASE_RESULT) &&
(p_evt->addr == RUNTIME_START_ADDR))
{
m_state = LOG_BACKEND_FLASH_ACTIVE;
}
}
/**
* @brief Function for enqueueing new message.
*
* If queue is full then the oldest message is freed.
*
* @param p_queue Queue.
* @param p_msg Message.
*
* @return Number of dropped messages
*/
static uint32_t message_enqueue(nrf_queue_t const * p_queue, nrf_log_entry_t * p_msg)
{
uint32_t dropped = 0;
//flag was set, busy so enqueue message
while (nrf_queue_push(p_queue, &p_msg) != NRF_SUCCESS)
{
nrf_log_entry_t * p_old_msg;
if (nrf_queue_pop(p_queue, &p_old_msg) == NRF_SUCCESS)
{
nrf_memobj_put(p_old_msg);
dropped++;
}
}
return dropped;
}
void nrf_log_backend_flashlog_put(nrf_log_backend_t const * p_backend,
nrf_log_entry_t * p_msg)
{
if (m_state == LOG_BACKEND_FLASH_ACTIVE)
{
nrf_memobj_get(p_msg);
m_dropped += message_enqueue(mp_flashlog_queue, p_msg);
if (nrf_atomic_flag_set_fetch(&m_busy_flag) == 0)
{
log_msg_queue_process(mp_flashlog_queue, false);
}
}
}
void nrf_log_backend_crashlog_put(nrf_log_backend_t const * p_backend,
nrf_log_entry_t * p_msg)
{
if (m_state != LOG_BACKEND_FLASH_INACTIVE)
{
nrf_memobj_get(p_msg);
UNUSED_RETURN_VALUE(message_enqueue(mp_crashlog_queue, p_msg));
}
if (m_state == LOG_BACKEND_FLASH_IN_PANIC)
{
log_msg_queue_process(mp_crashlog_queue, true);
}
}
void nrf_log_backend_flashlog_flush(nrf_log_backend_t const * p_backend)
{
queue_element_drop(mp_flashlog_queue);
}
void nrf_log_backend_crashlog_flush(nrf_log_backend_t const * p_backend)
{
queue_element_drop(mp_crashlog_queue);
}
void nrf_log_backend_flashlog_panic_set(nrf_log_backend_t const * p_backend)
{
/* Empty */
}
/**
* @brief Function for injecting log message which will indicate start of crash log.
*/
static void crashlog_marker_inject(void)
{
nrf_log_header_t crashlog_marker_hdr = {
.base = {
.std = {
.type = HEADER_TYPE_STD,
.severity = NRF_LOG_SEVERITY_INFO_RAW,
.nargs = 0,
.addr = (uint32_t)crashlog_str & STD_ADDR_MASK
}
},
.module_id = 0,
.timestamp = 0,
};
m_flash_buf[0] = crashlog_marker_hdr.base.raw;
m_flash_buf[1] = crashlog_marker_hdr.module_id;
m_flash_buf[2] = crashlog_marker_hdr.timestamp;
(void)nrf_fstorage_write(&m_log_flash_fstorage, m_curr_addr, m_flash_buf, LOG_HEADER_LEN, NULL);
m_curr_addr += LOG_HEADER_LEN;
}
void nrf_log_backend_crashlog_panic_set(nrf_log_backend_t const * p_backend)
{
if (nrf_fstorage_init(&m_log_flash_fstorage, &nrf_fstorage_nvmc, NULL) == NRF_SUCCESS)
{
m_state = LOG_BACKEND_FLASH_IN_PANIC;
/* In case of Softdevice MWU may protect access to NVMC. */
NVIC_DisableIRQ(MWU_IRQn);
log_msg_queue_process(mp_flashlog_queue, true);
crashlog_marker_inject();
log_msg_queue_process(mp_crashlog_queue, true);
}
else
{
m_state = LOG_BACKEND_FLASH_INACTIVE;
}
}
/**
* @brief Function for determining first empty location in area dedicated for flash logger backend.
*/
static uint32_t empty_addr_get(void)
{
uint32_t token = 0;
nrf_log_header_t * p_dummy_header;
uint8_t * p_dummy_data;
while(nrf_log_backend_flash_next_entry_get(&token, &p_dummy_header, &p_dummy_data) == NRF_SUCCESS)
{
}
return token;
}
ret_code_t nrf_log_backend_flash_init(nrf_fstorage_api_t const * p_fs_api)
{
ret_code_t err_code;
uint32_t start_addr = RUNTIME_START_ADDR;
uint32_t end_addr = start_addr + FLASH_LOG_SIZE - 1;
m_log_flash_fstorage.start_addr = start_addr;
m_log_flash_fstorage.end_addr = end_addr;
err_code = nrf_fstorage_init(&m_log_flash_fstorage, p_fs_api, NULL);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
m_curr_addr = empty_addr_get();
m_state = LOG_BACKEND_FLASH_ACTIVE;
return err_code;
}
ret_code_t nrf_log_backend_flash_next_entry_get(uint32_t * p_token,
nrf_log_header_t * * pp_header,
uint8_t * * pp_data)
{
uint32_t * p_addr = p_token;
uint32_t len;
*p_addr = (*p_addr == 0) ? RUNTIME_START_ADDR : *p_addr;
if (nrf_fstorage_rmap(&m_log_flash_fstorage, *p_addr) == NULL)
{
//Supports only memories which can be mapped for reading.
return NRF_ERROR_NOT_SUPPORTED;
}
if (msg_from_buf((uint32_t *)*p_addr, pp_header, pp_data, &len))
{
*p_addr += len;
return NRF_SUCCESS;
}
else
{
return NRF_ERROR_NOT_FOUND;
}
}
ret_code_t nrf_log_backend_flash_erase(void)
{
ret_code_t err_code;
m_state = LOG_BACKEND_FLASH_INACTIVE;
err_code = nrf_fstorage_erase(&m_log_flash_fstorage, RUNTIME_START_ADDR, NRF_LOG_BACKEND_PAGES, NULL);
m_curr_addr = RUNTIME_START_ADDR;
return err_code;
}
#if NRF_LOG_BACKEND_FLASHLOG_ENABLED
const nrf_log_backend_api_t nrf_log_backend_flashlog_api = {
.put = nrf_log_backend_flashlog_put,
.flush = nrf_log_backend_flashlog_flush,
.panic_set = nrf_log_backend_flashlog_panic_set,
};
#endif
#if NRF_LOG_BACKEND_CRASHLOG_ENABLED
const nrf_log_backend_api_t nrf_log_backend_crashlog_api = {
.put = nrf_log_backend_crashlog_put,
.flush = nrf_log_backend_crashlog_flush,
.panic_set = nrf_log_backend_crashlog_panic_set,
};
#endif
#if NRF_LOG_BACKEND_FLASH_CLI_CMDS
#include "nrf_cli.h"
static uint8_t m_buffer[64];
static nrf_cli_t const * mp_cli;
static void cli_tx(void const * p_context, char const * p_buffer, size_t len);
static nrf_fprintf_ctx_t m_fprintf_ctx =
{
.p_io_buffer = (char *)m_buffer,
.io_buffer_size = sizeof(m_buffer)-1,
.io_buffer_cnt = 0,
.auto_flush = true,
.p_user_ctx = &mp_cli,
.fwrite = cli_tx
};
static void flashlog_clear_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv)
{
if (nrf_cli_help_requested(p_cli))
{
nrf_cli_help_print(p_cli, NULL, 0);
}
UNUSED_RETURN_VALUE(nrf_log_backend_flash_erase());
}
#include "nrf_delay.h"
static void cli_tx(void const * p_context, char const * p_buffer, size_t len)
{
nrf_cli_t * * pp_cli = (nrf_cli_t * *)p_context;
char * p_strbuf = (char *)&p_buffer[len];
*p_strbuf = '\0';
nrf_cli_fprintf((nrf_cli_t const *)*pp_cli, NRF_CLI_DEFAULT, p_buffer);
// nrf_delay_ms(10);
}
static void entry_process(nrf_cli_t const * p_cli, nrf_log_header_t * p_header, uint8_t * p_data)
{
mp_cli = p_cli;
nrf_log_str_formatter_entry_params_t params =
{
.timestamp = p_header->timestamp,
.module_id = p_header->module_id,
.use_colors = 0,
};
switch (p_header->base.generic.type)
{
case HEADER_TYPE_STD:
{
params.severity = (nrf_log_severity_t)p_header->base.std.severity;
nrf_log_std_entry_process((const char *)((uint32_t)p_header->base.std.addr),
(uint32_t *)p_data,
p_header->base.std.nargs,
&params,
&m_fprintf_ctx);
break;
}
case HEADER_TYPE_HEXDUMP:
{
params.severity = (nrf_log_severity_t)p_header->base.hexdump.severity;
nrf_log_hexdump_entry_process(p_data,
p_header->base.hexdump.len,
&params,
&m_fprintf_ctx);
break;
}
default:
ASSERT(0);
}
}
static void flashlog_read_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv)
{
if (nrf_cli_help_requested(p_cli))
{
nrf_cli_help_print(p_cli, NULL, 0);
}
uint32_t token = 0;
uint8_t * p_data = NULL;
bool empty = true;
nrf_log_header_t * p_header;
while (1)
{
if (nrf_log_backend_flash_next_entry_get(&token, &p_header, &p_data) == NRF_SUCCESS)
{
entry_process(p_cli, p_header, p_data);
empty = false;
}
else
{
break;
}
}
if (empty)
{
nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Flash log empty\r\n");
}
}
static void flashlog_status_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv)
{
if (nrf_cli_help_requested(p_cli))
{
nrf_cli_help_print(p_cli, NULL, 0);
}
nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Flash log status:\r\n");
nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\t\t- Location (address: 0x%08X, length: %d)\r\n",
RUNTIME_START_ADDR, FLASH_LOG_SIZE);
nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\t\t- Current usage:%d%% (%d of %d bytes used)\r\n",
100ul * (m_curr_addr - RUNTIME_START_ADDR)/FLASH_LOG_SIZE,
m_curr_addr - RUNTIME_START_ADDR,
FLASH_LOG_SIZE);
nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\t\t- Dropped logs: %d\r\n", m_dropped);
}
NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_flashlog_cmd)
{
NRF_CLI_CMD(clear, NULL, "Remove logs", flashlog_clear_cmd),
NRF_CLI_CMD(read, NULL, "Read stored logs", flashlog_read_cmd),
NRF_CLI_CMD(status, NULL, "Flash log status", flashlog_status_cmd),
NRF_CLI_SUBCMD_SET_END
};
NRF_CLI_CMD_REGISTER(flashlog, &m_flashlog_cmd, "Commands for reading logs stored in non-volatile memory", NULL);
#endif //NRF_LOG_BACKEND_FLASH_CLI_CMDS
#endif //NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_FLASH)

View File

@ -0,0 +1,123 @@
/**
* 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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_RTT)
#include "nrf_log_backend_rtt.h"
#include "nrf_log_backend_serial.h"
#include "nrf_log_str_formatter.h"
#include "nrf_log_internal.h"
#include "nrf_delay.h"
#include <SEGGER_RTT_Conf.h>
#include <SEGGER_RTT.h>
static bool m_host_present;
static uint8_t m_string_buff[NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE];
void nrf_log_backend_rtt_init(void)
{
SEGGER_RTT_Init();
}
static void serial_tx(void const * p_context, char const * buffer, size_t len)
{
if (len)
{
uint32_t idx = 0;
uint32_t processed;
uint32_t watchdog_counter = NRF_LOG_BACKEND_RTT_TX_RETRY_CNT;
do
{
processed = SEGGER_RTT_WriteNoLock(0, &buffer[idx], len);
idx += processed;
len -= processed;
if (processed == 0)
{
/* There are two possible reasons for not writing any data to RTT:
* - The host is not connected and not reading the data.
* - The buffer got full and will be read by the host.
* These two situations are distinguished using the following algorithm.
* At the begining, the module assumes that the host is active,
* so when no data is read, it busy waits and retries.
* If, after retrying, the host reads the data, the module assumes that the host is active.
* If it fails, the module assumes that the host is inactive and stores that information. On next
* call, only one attempt takes place. The host is marked as active if the attempt is successful.
*/
if (!m_host_present)
{
break;
}
else
{
nrf_delay_ms(NRF_LOG_BACKEND_RTT_TX_RETRY_DELAY_MS);
watchdog_counter--;
if (watchdog_counter == 0)
{
m_host_present = false;
break;
}
}
}
m_host_present = true;
} while (len);
}
}
static void nrf_log_backend_rtt_put(nrf_log_backend_t const * p_backend,
nrf_log_entry_t * p_msg)
{
nrf_log_backend_serial_put(p_backend, p_msg, m_string_buff, NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE, serial_tx);
}
static void nrf_log_backend_rtt_flush(nrf_log_backend_t const * p_backend)
{
}
static void nrf_log_backend_rtt_panic_set(nrf_log_backend_t const * p_backend)
{
}
const nrf_log_backend_api_t nrf_log_backend_rtt_api = {
.put = nrf_log_backend_rtt_put,
.flush = nrf_log_backend_rtt_flush,
.panic_set = nrf_log_backend_rtt_panic_set,
};
#endif //NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_RTT)

View File

@ -0,0 +1,115 @@
/**
* 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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_LOG)
#include "nrf_log_backend_serial.h"
#include "nrf_log_str_formatter.h"
#include "nrf_log_internal.h"
void nrf_log_backend_serial_put(nrf_log_backend_t const * p_backend,
nrf_log_entry_t * p_msg,
uint8_t * p_buffer,
uint32_t length,
nrf_fprintf_fwrite tx_func)
{
nrf_memobj_get(p_msg);
nrf_fprintf_ctx_t fprintf_ctx = {
.p_io_buffer = (char *)p_buffer,
.io_buffer_size = length,
.io_buffer_cnt = 0,
.auto_flush = false,
.p_user_ctx = NULL,
.fwrite = tx_func
};
nrf_log_str_formatter_entry_params_t params;
nrf_log_header_t header;
uint32_t memobj_offset = 0;
nrf_memobj_read(p_msg, &header, HEADER_SIZE*sizeof(uint32_t), memobj_offset);
memobj_offset = HEADER_SIZE*sizeof(uint32_t);
params.timestamp = header.timestamp;
params.module_id = header.module_id;
params.dropped = header.dropped;
params.use_colors = NRF_LOG_USES_COLORS;
/*lint -save -e438*/
if (header.base.generic.type == HEADER_TYPE_STD)
{
char const * p_log_str = (char const *)((uint32_t)header.base.std.addr);
params.severity = (nrf_log_severity_t)header.base.std.severity;
uint32_t nargs = header.base.std.nargs;
uint32_t args[NRF_LOG_MAX_NUM_OF_ARGS];
nrf_memobj_read(p_msg, args, nargs*sizeof(uint32_t), memobj_offset);
memobj_offset += (nargs*sizeof(uint32_t));
nrf_log_std_entry_process(p_log_str,
args,
nargs,
&params,
&fprintf_ctx);
}
else if (header.base.generic.type == HEADER_TYPE_HEXDUMP)
{
uint32_t data_len = header.base.hexdump.len;
params.severity = (nrf_log_severity_t)header.base.hexdump.severity;
uint8_t data_buf[8];
uint32_t chunk_len;
do
{
chunk_len = sizeof(data_buf) > data_len ? data_len : sizeof(data_buf);
nrf_memobj_read(p_msg, data_buf, chunk_len, memobj_offset);
memobj_offset += chunk_len;
data_len -= chunk_len;
nrf_log_hexdump_entry_process(data_buf,
chunk_len,
&params,
&fprintf_ctx);
} while (data_len > 0);
}
nrf_memobj_put(p_msg);
/*lint -restore*/
}
#endif //NRF_LOG_ENABLED

View File

@ -0,0 +1,77 @@
/**
* 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.
*
*/
#ifndef NRF_LOG_BACKEND_SERIAL_H
#define NRF_LOG_BACKEND_SERIAL_H
/**@file
* @addtogroup nrf_log Logger module
* @ingroup app_common
*
* @defgroup nrf_log_backend_serial Common part of serial backends
* @{
* @ingroup nrf_log
* @brief The nrf_log serial backend common put function.
*/
#include "nrf_log_backend_interface.h"
#include "nrf_fprintf.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief A function for processing logger entry with simple serial interface as output.
*
*
*/
void nrf_log_backend_serial_put(nrf_log_backend_t const * p_backend,
nrf_log_entry_t * p_msg,
uint8_t * p_buffer,
uint32_t length,
nrf_fprintf_fwrite tx_func);
#endif //NRF_LOG_BACKEND_SERIAL_H
#ifdef __cplusplus
}
#endif
/** @} */

View File

@ -0,0 +1,116 @@
/**
* 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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_UART)
#include "nrf_log_backend_uart.h"
#include "nrf_log_backend_serial.h"
#include "nrf_log_internal.h"
#include "nrf_drv_uart.h"
#include "app_error.h"
nrf_drv_uart_t m_uart = NRF_DRV_UART_INSTANCE(0);
static uint8_t m_string_buff[NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE];
static volatile bool m_xfer_done;
static bool m_async_mode;
static void uart_evt_handler(nrf_drv_uart_event_t * p_event, void * p_context)
{
m_xfer_done = true;
}
static void uart_init(bool async_mode)
{
nrf_drv_uart_config_t config = NRF_DRV_UART_DEFAULT_CONFIG;
config.pseltxd = NRF_LOG_BACKEND_UART_TX_PIN;
config.pselrxd = NRF_UART_PSEL_DISCONNECTED;
config.pselcts = NRF_UART_PSEL_DISCONNECTED;
config.pselrts = NRF_UART_PSEL_DISCONNECTED;
config.baudrate = (nrf_uart_baudrate_t)NRF_LOG_BACKEND_UART_BAUDRATE;
ret_code_t err_code = nrf_drv_uart_init(&m_uart, &config, async_mode ? uart_evt_handler : NULL);
APP_ERROR_CHECK(err_code);
m_async_mode = async_mode;
}
void nrf_log_backend_uart_init(void)
{
bool async_mode = NRF_LOG_DEFERRED ? true : false;
uart_init(async_mode);
}
static void serial_tx(void const * p_context, char const * p_buffer, size_t len)
{
uint8_t len8 = (uint8_t)(len & 0x000000FF);
m_xfer_done = false;
ret_code_t err_code = nrf_drv_uart_tx(&m_uart, (uint8_t *)p_buffer, len8);
APP_ERROR_CHECK(err_code);
/* wait for completion since buffer is reused*/
while (m_async_mode && (m_xfer_done == false))
{
}
}
static void nrf_log_backend_uart_put(nrf_log_backend_t const * p_backend,
nrf_log_entry_t * p_msg)
{
nrf_log_backend_serial_put(p_backend, p_msg, m_string_buff,
NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE, serial_tx);
}
static void nrf_log_backend_uart_flush(nrf_log_backend_t const * p_backend)
{
}
static void nrf_log_backend_uart_panic_set(nrf_log_backend_t const * p_backend)
{
nrf_drv_uart_uninit(&m_uart);
uart_init(false);
}
const nrf_log_backend_api_t nrf_log_backend_uart_api = {
.put = nrf_log_backend_uart_put,
.flush = nrf_log_backend_uart_flush,
.panic_set = nrf_log_backend_uart_panic_set,
};
#endif //NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_UART)

View File

@ -0,0 +1,80 @@
/**
* 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.
*
*/
#ifndef NRF_LOG_CTRL_INTERNAL_H
#define NRF_LOG_CTRL_INTERNAL_H
/**
* @cond (NODOX)
* @defgroup nrf_log_ctrl_internal Auxiliary internal types declarations
* @{
* @internal
*/
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_LOG)
#define NRF_LOG_INTERNAL_INIT(...) \
nrf_log_init(GET_VA_ARG_1(__VA_ARGS__), \
GET_VA_ARG_1(GET_ARGS_AFTER_1(__VA_ARGS__, NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY)))
#define NRF_LOG_INTERNAL_PROCESS() nrf_log_frontend_dequeue()
#define NRF_LOG_INTERNAL_FLUSH() \
do { \
while (NRF_LOG_INTERNAL_PROCESS()); \
} while (0)
#define NRF_LOG_INTERNAL_FINAL_FLUSH() \
do { \
nrf_log_panic(); \
NRF_LOG_INTERNAL_FLUSH(); \
} while (0)
#else // NRF_MODULE_ENABLED(NRF_LOG)
#define NRF_LOG_INTERNAL_PROCESS() false
#define NRF_LOG_INTERNAL_FLUSH()
#define NRF_LOG_INTERNAL_INIT(timestamp_func) NRF_SUCCESS
#define NRF_LOG_INTERNAL_HANDLERS_SET(default_handler, bytes_handler) \
UNUSED_PARAMETER(default_handler); UNUSED_PARAMETER(bytes_handler)
#define NRF_LOG_INTERNAL_FINAL_FLUSH()
#endif // NRF_MODULE_ENABLED(NRF_LOG)
/** @}
* @endcond
*/
#endif // NRF_LOG_CTRL_INTERNAL_H

View File

@ -0,0 +1,76 @@
/**
* 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_LOG)
#include "nrf_log_default_backends.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_internal.h"
#include "nrf_assert.h"
#if defined(NRF_LOG_BACKEND_RTT_ENABLED) && NRF_LOG_BACKEND_RTT_ENABLED
#include "nrf_log_backend_rtt.h"
NRF_LOG_BACKEND_RTT_DEF(rtt_log_backend);
#endif
#if defined(NRF_LOG_BACKEND_UART_ENABLED) && NRF_LOG_BACKEND_UART_ENABLED
#include "nrf_log_backend_uart.h"
NRF_LOG_BACKEND_UART_DEF(uart_log_backend);
#endif
void nrf_log_default_backends_init(void)
{
int32_t backend_id = -1;
(void)backend_id;
#if defined(NRF_LOG_BACKEND_RTT_ENABLED) && NRF_LOG_BACKEND_RTT_ENABLED
nrf_log_backend_rtt_init();
backend_id = nrf_log_backend_add(&rtt_log_backend.backend, NRF_LOG_SEVERITY_DEBUG);
ASSERT(backend_id >= 0);
nrf_log_backend_enable(&rtt_log_backend.backend);
#endif
#if defined(NRF_LOG_BACKEND_UART_ENABLED) && NRF_LOG_BACKEND_UART_ENABLED
nrf_log_backend_uart_init();
backend_id = nrf_log_backend_add(&uart_log_backend.backend, NRF_LOG_SEVERITY_DEBUG);
ASSERT(backend_id >= 0);
nrf_log_backend_enable(&uart_log_backend.backend);
#endif
}
#endif

View File

@ -0,0 +1,529 @@
/**
* 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.
*
*/
#ifndef NRF_LOG_INTERNAL_H__
#define NRF_LOG_INTERNAL_H__
#include "sdk_common.h"
#include "nrf.h"
#include "nrf_error.h"
#include "app_util.h"
#include <stdint.h>
#include <stdbool.h>
#include "nrf_log_instance.h"
#include "nrf_log_types.h"
#ifndef NRF_LOG_ERROR_COLOR
#define NRF_LOG_ERROR_COLOR NRF_LOG_COLOR_DEFAULT
#endif
#ifndef NRF_LOG_WARNING_COLOR
#define NRF_LOG_WARNING_COLOR NRF_LOG_COLOR_DEFAULT
#endif
#ifndef NRF_LOG_INFO_COLOR
#define NRF_LOG_INFO_COLOR NRF_LOG_COLOR_DEFAULT
#endif
#ifndef NRF_LOG_DEBUG_COLOR
#define NRF_LOG_DEBUG_COLOR NRF_LOG_COLOR_DEFAULT
#endif
#ifndef NRF_LOG_COLOR_DEFAULT
#define NRF_LOG_COLOR_DEFAULT 0
#endif
#ifndef NRF_LOG_DEFAULT_LEVEL
#define NRF_LOG_DEFAULT_LEVEL 0
#endif
#ifndef NRF_LOG_USES_COLORS
#define NRF_LOG_USES_COLORS 0
#endif
#ifndef NRF_LOG_USES_TIMESTAMP
#define NRF_LOG_USES_TIMESTAMP 0
#endif
#ifndef NRF_LOG_FILTERS_ENABLED
#define NRF_LOG_FILTERS_ENABLED 0
#endif
#ifndef NRF_LOG_MODULE_NAME
#define NRF_LOG_MODULE_NAME app
#endif
#define NRF_LOG_LEVEL_BITS 3
#define NRF_LOG_LEVEL_MASK ((1UL << NRF_LOG_LEVEL_BITS) - 1)
#define NRF_LOG_MODULE_ID_BITS 16
#define NRF_LOG_MODULE_ID_POS 16
#define NRF_LOG_MAX_NUM_OF_ARGS 6
#if NRF_LOG_FILTERS_ENABLED && NRF_LOG_ENABLED
#define NRF_LOG_FILTER NRF_LOG_ITEM_DATA_DYNAMIC(NRF_LOG_MODULE_NAME).filter
#define NRF_LOG_INST_FILTER(p_inst) (p_inst)->filter
#else
#undef NRF_LOG_FILTER
#define NRF_LOG_FILTER NRF_LOG_SEVERITY_DEBUG
#define NRF_LOG_INST_FILTER(p_inst) NRF_LOG_SEVERITY_DEBUG
#endif
#if NRF_LOG_ENABLED
#define NRF_LOG_MODULE_ID NRF_LOG_ITEM_DATA_DYNAMIC(NRF_LOG_MODULE_NAME).module_id
#define NRF_LOG_INST_ID(p_inst) (p_inst)->module_id
#else
#define NRF_LOG_MODULE_ID 0
#define NRF_LOG_INST_ID(p_inst) 0
#endif
#define LOG_INTERNAL_X(N, ...) CONCAT_2(LOG_INTERNAL_, N) (__VA_ARGS__)
#define LOG_INTERNAL(type, ...) LOG_INTERNAL_X(NUM_VA_ARGS_LESS_1( \
__VA_ARGS__), type, __VA_ARGS__)
#if NRF_LOG_ENABLED
#define NRF_LOG_INTERNAL_LOG_PUSH(_str) nrf_log_push(_str)
#define LOG_INTERNAL_0(type, str) \
nrf_log_frontend_std_0(type, str)
#define LOG_INTERNAL_1(type, str, arg0) \
/*lint -save -e571*/nrf_log_frontend_std_1(type, str, (uint32_t)(arg0))/*lint -restore*/
#define LOG_INTERNAL_2(type, str, arg0, arg1) \
/*lint -save -e571*/nrf_log_frontend_std_2(type, str, (uint32_t)(arg0), \
(uint32_t)(arg1))/*lint -restore*/
#define LOG_INTERNAL_3(type, str, arg0, arg1, arg2) \
/*lint -save -e571*/nrf_log_frontend_std_3(type, str, (uint32_t)(arg0), \
(uint32_t)(arg1), (uint32_t)(arg2))/*lint -restore*/
#define LOG_INTERNAL_4(type, str, arg0, arg1, arg2, arg3) \
/*lint -save -e571*/nrf_log_frontend_std_4(type, str, (uint32_t)(arg0), \
(uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3))/*lint -restore*/
#define LOG_INTERNAL_5(type, str, arg0, arg1, arg2, arg3, arg4) \
/*lint -save -e571*/nrf_log_frontend_std_5(type, str, (uint32_t)(arg0), \
(uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3), (uint32_t)(arg4))/*lint -restore*/
#define LOG_INTERNAL_6(type, str, arg0, arg1, arg2, arg3, arg4, arg5) \
/*lint -save -e571*/nrf_log_frontend_std_6(type, str, (uint32_t)(arg0), \
(uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3), (uint32_t)(arg4), (uint32_t)(arg5))/*lint -restore*/
#else //NRF_LOG_ENABLED
#define NRF_LOG_INTERNAL_LOG_PUSH(_str) (void)(_str)
#define LOG_INTERNAL_0(_type, _str) \
(void)(_type); (void)(_str)
#define LOG_INTERNAL_1(_type, _str, _arg0) \
(void)(_type); (void)(_str); (void)(_arg0)
#define LOG_INTERNAL_2(_type, _str, _arg0, _arg1) \
(void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1)
#define LOG_INTERNAL_3(_type, _str, _arg0, _arg1, _arg2) \
(void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2)
#define LOG_INTERNAL_4(_type, _str, _arg0, _arg1, _arg2, _arg3) \
(void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3)
#define LOG_INTERNAL_5(_type, _str, _arg0, _arg1, _arg2, _arg3, _arg4) \
(void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3); (void)(_arg4)
#define LOG_INTERNAL_6(_type, _str, _arg0, _arg1, _arg2, _arg3, _arg4, _arg5) \
(void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3); (void)(_arg4); (void)(_arg5)
#endif //NRF_LOG_ENABLED
#define LOG_SEVERITY_MOD_ID(severity) ((severity) | NRF_LOG_MODULE_ID << NRF_LOG_MODULE_ID_POS)
#define LOG_SEVERITY_INST_ID(severity,p_inst) ((severity) | NRF_LOG_INST_ID(p_inst) << NRF_LOG_MODULE_ID_POS)
#if NRF_LOG_ENABLED
#define LOG_HEXDUMP(_severity, _p_data, _length) \
nrf_log_frontend_hexdump((_severity), (_p_data), (_length))
#else
#define LOG_HEXDUMP(_severity, _p_data, _length) \
(void)(_severity); (void)(_p_data); (void)_length
#endif
#define NRF_LOG_INTERNAL_INST(level, level_id, p_inst, ...) \
if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \
(level <= NRF_LOG_DEFAULT_LEVEL)) \
{ \
if (NRF_LOG_INST_FILTER(p_inst) >= level) \
{ \
LOG_INTERNAL(LOG_SEVERITY_INST_ID(level_id, p_inst), __VA_ARGS__); \
} \
}
#define NRF_LOG_INTERNAL_MODULE(level, level_id, ...) \
if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \
(level <= NRF_LOG_DEFAULT_LEVEL)) \
{ \
if (NRF_LOG_FILTER >= level) \
{ \
LOG_INTERNAL(LOG_SEVERITY_MOD_ID(level_id), __VA_ARGS__); \
} \
}
#define NRF_LOG_INTERNAL_HEXDUMP_INST(level, level_id, p_inst, p_data, len) \
if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \
(level <= NRF_LOG_DEFAULT_LEVEL)) \
{ \
if (NRF_LOG_INST_FILTER(p_inst) >= level) \
{ \
LOG_HEXDUMP(LOG_SEVERITY_INST_ID(level_id, p_inst), \
(p_data), (len)); \
} \
}
#define NRF_LOG_INTERNAL_HEXDUMP_MODULE(level, level_id, p_data, len) \
if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \
(level <= NRF_LOG_DEFAULT_LEVEL)) \
{ \
if (NRF_LOG_FILTER >= level) \
{ \
LOG_HEXDUMP(LOG_SEVERITY_MOD_ID(level_id), \
(p_data), (len)); \
} \
}
#define NRF_LOG_INTERNAL_INST_ERROR(p_inst, ...) \
NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_inst, __VA_ARGS__)
#define NRF_LOG_INTERNAL_ERROR(...) \
NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR,__VA_ARGS__)
#define NRF_LOG_INTERNAL_HEXDUMP_INST_ERROR(p_inst, p_data, len) \
NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_inst, p_data, len)
#define NRF_LOG_INTERNAL_HEXDUMP_ERROR(p_data, len) \
NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_data, len)
#define NRF_LOG_INTERNAL_INST_WARNING(p_inst, ...) \
NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_inst, __VA_ARGS__)
#define NRF_LOG_INTERNAL_WARNING(...) \
NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING,__VA_ARGS__)
#define NRF_LOG_INTERNAL_HEXDUMP_INST_WARNING(p_inst, p_data, len) \
NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_inst, p_data, len)
#define NRF_LOG_INTERNAL_HEXDUMP_WARNING(p_data, len) \
NRF_LOG_INTERNAL_HEXDUMP_(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_data, len)
#define NRF_LOG_INTERNAL_INST_INFO(p_inst, ...) \
NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_inst, __VA_ARGS__)
#define NRF_LOG_INTERNAL_INFO(...) \
NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, __VA_ARGS__)
#define NRF_LOG_INTERNAL_HEXDUMP_INST_INFO(p_inst, p_data, len) \
NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_inst, p_data, len)
#define NRF_LOG_INTERNAL_HEXDUMP_INFO(p_data, len) \
NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_data, len)
#define NRF_LOG_INTERNAL_RAW_INFO(...) \
NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO_RAW, __VA_ARGS__)
#define NRF_LOG_INTERNAL_RAW_HEXDUMP_INFO(p_data, len) \
NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO_RAW, p_data, len)
#define NRF_LOG_INTERNAL_INST_DEBUG(p_inst, ...) \
NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_inst, __VA_ARGS__)
#define NRF_LOG_INTERNAL_DEBUG(...) \
NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, __VA_ARGS__)
#define NRF_LOG_INTERNAL_HEXDUMP_INST_DEBUG(p_inst, p_data, len) \
NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_inst, p_data, len)
#define NRF_LOG_INTERNAL_HEXDUMP_DEBUG(p_data, len) \
NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_data, len)
#if NRF_LOG_ENABLED
#ifdef UNIT_TEST
#define COMPILED_LOG_LEVEL 4
#else
#define COMPILED_LOG_LEVEL NRF_LOG_LEVEL
#endif
#define NRF_LOG_INTERNAL_MODULE_REGISTER() \
NRF_LOG_INTERNAL_ITEM_REGISTER(NRF_LOG_MODULE_NAME, \
STRINGIFY(NRF_LOG_MODULE_NAME), \
NRF_LOG_INFO_COLOR, \
NRF_LOG_DEBUG_COLOR, \
NRF_LOG_INITIAL_LEVEL, \
COMPILED_LOG_LEVEL)
#else
#define NRF_LOG_INTERNAL_MODULE_REGISTER() /*lint -save -e19*/ /*lint -restore*/
#endif
extern NRF_LOG_DYNAMIC_STRUCT_NAME NRF_LOG_ITEM_DATA_DYNAMIC(NRF_LOG_MODULE_NAME);
/**
* Set of macros for encoding and decoding header for log entries.
* There are 3 types of entries:
* 1. Standard entry (STD)
* An entry consists of header, pointer to string and values. Header contains
* severity leveland determines number of arguments and thus size of the entry.
* Since flash address space starts from 0x00000000 and is limited to kB rather
* than MB 22 bits are used to store the address (4MB). It is used that way to
* save one RAM memory.
*
* --------------------------------
* |TYPE|SEVERITY|NARGS| P_STR |
* |------------------------------|
* | Module_ID (optional) |
* |------------------------------|
* | TIMESTAMP (optional) |
* |------------------------------|
* | ARG0 |
* |------------------------------|
* | .... |
* |------------------------------|
* | ARG(nargs-1) |
* --------------------------------
*
* 2. Hexdump entry (HEXDUMP) is used for dumping raw data. An entry consists of
* header, optional timestamp, pointer to string and data. A header contains
* length (10bit) and offset which is updated after backend processes part of
* data.
*
* --------------------------------
* |TYPE|SEVERITY|NARGS|OFFSET|LEN|
* |------------------------------|
* | Module_ID (optional) |
* |------------------------------|
* | TIMESTAMP (optional) |
* |------------------------------|
* | P_STR |
* |------------------------------|
* | data |
* |------------------------------|
* | data | dummy |
* --------------------------------
*
* 3. Pushed string. If string is pushed into the logger internal buffer it is
* stored as PUSHED entry. It consists of header, unused data (optional) and
* string. Unused data is present if string does not not fit into a buffer
* without wrapping (and string cannot be wrapped). In that case header
* contains information about offset.
*
* --------------------------------
* |TYPE| OFFSET | LEN |
* |------------------------------|
* | OFFSET |
* |------------------------------|
* end| OFFSET |
* 0|------------------------------|
* | STRING |
* |------------------------------|
* | STRING | dummy |
* --------------------------------
*/
#define STD_ADDR_MASK ((uint32_t)(1U << 22) - 1U)
#define HEADER_TYPE_STD 1U
#define HEADER_TYPE_HEXDUMP 2U
#define HEADER_TYPE_PUSHED 0U
#define HEADER_TYPE_INVALID 3U
typedef struct
{
uint32_t type : 2;
uint32_t in_progress: 1;
uint32_t data : 29;
} nrf_log_generic_header_t;
typedef struct
{
uint32_t type : 2;
uint32_t in_progress: 1;
uint32_t severity : 3;
uint32_t nargs : 4;
uint32_t addr : 22;
} nrf_log_std_header_t;
typedef struct
{
uint32_t type : 2;
uint32_t in_progress: 1;
uint32_t severity : 3;
uint32_t offset : 10;
uint32_t reserved : 6;
uint32_t len : 10;
} nrf_log_hexdump_header_t;
typedef struct
{
uint32_t type : 2;
uint32_t reserved0 : 4;
uint32_t offset : 10;
uint32_t reserved1 : 6;
uint32_t len : 10;
} nrf_log_pushed_header_t;
typedef union
{
nrf_log_generic_header_t generic;
nrf_log_std_header_t std;
nrf_log_hexdump_header_t hexdump;
nrf_log_pushed_header_t pushed;
uint32_t raw;
} nrf_log_main_header_t;
typedef struct
{
nrf_log_main_header_t base;
uint16_t module_id;
uint16_t dropped;
uint32_t timestamp;
} nrf_log_header_t;
#define HEADER_SIZE (sizeof(nrf_log_header_t)/sizeof(uint32_t) - \
(NRF_LOG_USES_TIMESTAMP ? 0 : 1))
#define PUSHED_HEADER_SIZE (sizeof(nrf_log_pushed_header_t)/sizeof(uint32_t))
//Implementation assumes that pushed header has one word.
STATIC_ASSERT(PUSHED_HEADER_SIZE == 1);
/**
* @brief A function for logging raw string.
*
* @param severity_mid Severity.
* @param p_str A pointer to a string.
*/
void nrf_log_frontend_std_0(uint32_t severity_mid, char const * const p_str);
/**
* @brief A function for logging a formatted string with one argument.
*
* @param severity_mid Severity.
* @param p_str A pointer to a formatted string.
* @param val0 An argument.
*/
void nrf_log_frontend_std_1(uint32_t severity_mid,
char const * const p_str,
uint32_t val0);
/**
* @brief A function for logging a formatted string with 2 arguments.
*
* @param severity_mid Severity.
* @param p_str A pointer to a formatted string.
* @param val0, val1 Arguments for formatting string.
*/
void nrf_log_frontend_std_2(uint32_t severity_mid,
char const * const p_str,
uint32_t val0,
uint32_t val1);
/**
* @brief A function for logging a formatted string with 3 arguments.
*
* @param severity_mid Severity.
* @param p_str A pointer to a formatted string.
* @param val0, val1, val2 Arguments for formatting string.
*/
void nrf_log_frontend_std_3(uint32_t severity_mid,
char const * const p_str,
uint32_t val0,
uint32_t val1,
uint32_t val2);
/**
* @brief A function for logging a formatted string with 4 arguments.
*
* @param severity_mid Severity.
* @param p_str A pointer to a formatted string.
* @param val0, val1, val2, val3 Arguments for formatting string.
*/
void nrf_log_frontend_std_4(uint32_t severity_mid,
char const * const p_str,
uint32_t val0,
uint32_t val1,
uint32_t val2,
uint32_t val3);
/**
* @brief A function for logging a formatted string with 5 arguments.
*
* @param severity_mid Severity.
* @param p_str A pointer to a formatted string.
* @param val0, val1, val2, val3, val4 Arguments for formatting string.
*/
void nrf_log_frontend_std_5(uint32_t severity_mid,
char const * const p_str,
uint32_t val0,
uint32_t val1,
uint32_t val2,
uint32_t val3,
uint32_t val4);
/**
* @brief A function for logging a formatted string with 6 arguments.
*
* @param severity_mid Severity.
* @param p_str A pointer to a formatted string.
* @param val0, val1, val2, val3, val4, val5 Arguments for formatting string.
*/
void nrf_log_frontend_std_6(uint32_t severity_mid,
char const * const p_str,
uint32_t val0,
uint32_t val1,
uint32_t val2,
uint32_t val3,
uint32_t val4,
uint32_t val5);
/**
* @brief A function for logging raw data.
*
* @param severity_mid Severity.
* @param p_str A pointer to a string which is prefixing the data.
* @param p_data A pointer to data to be dumped.
* @param length Length of data (in bytes).
*
*/
void nrf_log_frontend_hexdump(uint32_t severity_mid,
const void * const p_data,
uint16_t length);
/**
* @brief A function for reading a byte from log backend.
*
* @return Byte.
*/
uint8_t nrf_log_getchar(void);
#endif // NRF_LOG_INTERNAL_H__

View File

@ -0,0 +1,256 @@
/**
* 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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_LOG)
#include "nrf_log_str_formatter.h"
#include "nrf_log_internal.h"
#include "nrf_log_ctrl.h"
#include "nrf_fprintf.h"
#include <ctype.h>
#define NRF_LOG_COLOR_CODE_DEFAULT "\x1B[0m"
#define NRF_LOG_COLOR_CODE_BLACK "\x1B[1;30m"
#define NRF_LOG_COLOR_CODE_RED "\x1B[1;31m"
#define NRF_LOG_COLOR_CODE_GREEN "\x1B[1;32m"
#define NRF_LOG_COLOR_CODE_YELLOW "\x1B[1;33m"
#define NRF_LOG_COLOR_CODE_BLUE "\x1B[1;34m"
#define NRF_LOG_COLOR_CODE_MAGENTA "\x1B[1;35m"
#define NRF_LOG_COLOR_CODE_CYAN "\x1B[1;36m"
#define NRF_LOG_COLOR_CODE_WHITE "\x1B[1;37m"
static const char * severity_names[] = {
NULL,
"error",
"warning",
"info",
"debug"
};
static const char * m_colors[] = {
NRF_LOG_COLOR_CODE_DEFAULT,
NRF_LOG_COLOR_CODE_BLACK,
NRF_LOG_COLOR_CODE_RED,
NRF_LOG_COLOR_CODE_GREEN,
NRF_LOG_COLOR_CODE_YELLOW,
NRF_LOG_COLOR_CODE_BLUE,
NRF_LOG_COLOR_CODE_MAGENTA,
NRF_LOG_COLOR_CODE_CYAN,
NRF_LOG_COLOR_CODE_WHITE,
};
static uint32_t m_freq;
static uint32_t m_timestamp_div;
static void timestamp_print(nrf_fprintf_ctx_t * p_ctx, uint32_t timestamp)
{
if (NRF_LOG_USES_TIMESTAMP)
{
if (NRF_LOG_STR_FORMATTER_TIMESTAMP_FORMAT_ENABLED)
{
timestamp /= m_timestamp_div;
uint32_t seconds = timestamp/m_freq;
uint32_t hours = seconds/3600;
seconds -= hours * 3600;
uint32_t mins = seconds/60;
seconds -= mins * 60;
uint32_t reminder = timestamp % m_freq;
uint32_t ms = (reminder * 1000)/m_freq;
uint32_t us = (1000*(1000*reminder - (ms * m_freq)))/m_freq;
nrf_fprintf(p_ctx, "[%02d:%02d:%02d.%03d,%03d] ", hours, mins, seconds, ms, us);
}
else
{
nrf_fprintf(p_ctx, "[%08lu] ", timestamp);
}
}
}
static void prefix_process(nrf_log_str_formatter_entry_params_t * p_params,
nrf_fprintf_ctx_t * p_ctx)
{
if (p_params->dropped)
{
nrf_fprintf(p_ctx,
"%sLogs dropped (%d)%s\r\n",
NRF_LOG_COLOR_CODE_RED,
p_params->dropped,
NRF_LOG_COLOR_CODE_DEFAULT);
}
if (!(p_params->severity == NRF_LOG_SEVERITY_INFO_RAW))
{
if (p_params->use_colors)
{
nrf_fprintf(p_ctx, "%s",
m_colors[nrf_log_color_id_get( p_params->module_id, p_params->severity)]);
}
timestamp_print(p_ctx, p_params->timestamp);
nrf_fprintf(p_ctx, "<%s> %s: ",
severity_names[p_params->severity], nrf_log_module_name_get(p_params->module_id, false));
}
}
static void postfix_process(nrf_log_str_formatter_entry_params_t * p_params,
nrf_fprintf_ctx_t * p_ctx,
bool newline)
{
if (!(p_params->severity == NRF_LOG_SEVERITY_INFO_RAW))
{
if (p_params->use_colors)
{
nrf_fprintf(p_ctx, "%s", m_colors[0]);
}
nrf_fprintf(p_ctx, "\r\n");
}
else if (newline)
{
nrf_fprintf(p_ctx, "\r\n");
}
nrf_fprintf_buffer_flush(p_ctx);
}
void nrf_log_std_entry_process(char const * p_str,
uint32_t const * p_args,
uint32_t nargs,
nrf_log_str_formatter_entry_params_t * p_params,
nrf_fprintf_ctx_t * p_ctx)
{
bool auto_flush = p_ctx->auto_flush;
p_ctx->auto_flush = false;
prefix_process(p_params, p_ctx);
switch (nargs)
{
case 0:
nrf_fprintf(p_ctx, p_str);
break;
case 1:
nrf_fprintf(p_ctx, p_str, p_args[0]);
break;
case 2:
nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1]);
break;
case 3:
nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2]);
break;
case 4:
nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2], p_args[3]);
break;
case 5:
nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2], p_args[3], p_args[4]);
break;
case 6:
nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2], p_args[3], p_args[4], p_args[5]);
break;
default:
break;
}
postfix_process(p_params, p_ctx, false);
p_ctx->auto_flush = auto_flush;
}
#define HEXDUMP_BYTES_IN_LINE 8
void nrf_log_hexdump_entry_process(uint8_t * p_data,
uint32_t data_len,
nrf_log_str_formatter_entry_params_t * p_params,
nrf_fprintf_ctx_t * p_ctx)
{
if (data_len > HEXDUMP_BYTES_IN_LINE)
{
return;
}
bool auto_flush = p_ctx->auto_flush;
p_ctx->auto_flush = false;
prefix_process(p_params, p_ctx);
uint32_t i;
for (i = 0; i < HEXDUMP_BYTES_IN_LINE; i++)
{
if (i < data_len)
{
nrf_fprintf(p_ctx, " %02x", p_data[i]);
}
else
{
nrf_fprintf(p_ctx, " ");
}
}
nrf_fprintf(p_ctx, "|");
for (i = 0; i < HEXDUMP_BYTES_IN_LINE; i++)
{
if (i < data_len)
{
char c = (char)p_data[i];
nrf_fprintf(p_ctx, "%c", isprint((int)c) ? c :'.');
}
else
{
nrf_fprintf(p_ctx, " ");
}
}
postfix_process(p_params, p_ctx, true);
p_ctx->auto_flush = auto_flush;
}
void nrf_log_str_formatter_timestamp_freq_set(uint32_t freq)
{
m_timestamp_div = 1;
/* There is no point to have frequency higher than 1MHz (ns are not printed) and too high
* frequency leads to overflows in calculations.
*/
while (freq > 1000000)
{
freq /= 2;
m_timestamp_div *= 2;
}
m_freq = freq;
}
#endif //NRF_LOG_ENABLED

View File

@ -0,0 +1,231 @@
/**
* 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 "nrf_memobj.h"
#include "nrf_atomic.h"
#include "nrf_assert.h"
typedef struct memobj_elem_s memobj_elem_t;
typedef struct
{
memobj_elem_t * p_next;
} memobj_header_t;
typedef struct
{
uint8_t user_cnt;
uint8_t chunk_cnt;
uint16_t chunk_size;
} memobj_head_header_fields_t;
typedef struct
{
union
{
nrf_atomic_u32_t atomic_user_cnt;
memobj_head_header_fields_t fields;
} data;
} memobj_head_header_t;
typedef struct
{
memobj_header_t header;
memobj_head_header_t head_header;
uint8_t data[1];
} memobj_head_t;
STATIC_ASSERT(sizeof(memobj_header_t) == NRF_MEMOBJ_STD_HEADER_SIZE);
struct memobj_elem_s
{
memobj_header_t header;
uint8_t data[1];
};
ret_code_t nrf_memobj_pool_init(nrf_memobj_pool_t const * p_pool)
{
return nrf_balloc_init((nrf_balloc_t const *)p_pool);
}
nrf_memobj_t * nrf_memobj_alloc(nrf_memobj_pool_t const * p_pool,
size_t size)
{
uint32_t bsize = (uint32_t)NRF_BALLOC_ELEMENT_SIZE((nrf_balloc_t const *)p_pool) - sizeof(memobj_header_t);
uint8_t num_of_chunks = (uint8_t)CEIL_DIV(size + sizeof(memobj_head_header_t), bsize);
memobj_head_t * p_head = nrf_balloc_alloc((nrf_balloc_t const *)p_pool);
if (p_head == NULL)
{
return NULL;
}
p_head->head_header.data.fields.user_cnt = 0;
p_head->head_header.data.fields.chunk_cnt = 1;
p_head->head_header.data.fields.chunk_size = bsize;
memobj_header_t * p_prev = (memobj_header_t *)p_head;
memobj_header_t * p_curr;
uint32_t i;
uint32_t chunk_less1 = (uint32_t)num_of_chunks - 1;
p_prev->p_next = (memobj_elem_t *)p_pool;
for (i = 0; i < chunk_less1; i++)
{
p_curr = (memobj_header_t *)nrf_balloc_alloc((nrf_balloc_t const *)p_pool);
if (p_curr)
{
(p_head->head_header.data.fields.chunk_cnt)++;
p_prev->p_next = (memobj_elem_t *)p_curr;
p_curr->p_next = (memobj_elem_t *)p_pool;
p_prev = p_curr;
}
else
{
//Couldn't allocate all requested buffers
nrf_memobj_free((nrf_memobj_t *)p_head);
return NULL;
}
}
return (nrf_memobj_t *)p_head;
}
void nrf_memobj_free(nrf_memobj_t * p_obj)
{
memobj_head_t * p_head = (memobj_head_t *)p_obj;
uint8_t chunk_cnt = p_head->head_header.data.fields.chunk_cnt;
uint32_t i;
memobj_header_t * p_curr = (memobj_header_t *)p_obj;
memobj_header_t * p_next;
uint32_t chunk_less1 = (uint32_t)chunk_cnt - 1;
for (i = 0; i < chunk_less1; i++)
{
p_curr = (memobj_header_t *)p_curr->p_next;
}
nrf_balloc_t const * p_pool2 = (nrf_balloc_t const *)p_curr->p_next;
p_curr = (memobj_header_t *)p_obj;
for (i = 0; i < chunk_cnt; i++)
{
p_next = (memobj_header_t *)p_curr->p_next;
nrf_balloc_free(p_pool2, p_curr);
p_curr = p_next;
}
}
void nrf_memobj_get(nrf_memobj_t const * p_obj)
{
memobj_head_t * p_head = (memobj_head_t *)p_obj;
(void)nrf_atomic_u32_add(&p_head->head_header.data.atomic_user_cnt, 1);
}
void nrf_memobj_put(nrf_memobj_t * p_obj)
{
memobj_head_t * p_head = (memobj_head_t *)p_obj;
uint32_t user_cnt = nrf_atomic_u32_sub(&p_head->head_header.data.atomic_user_cnt, 1);
memobj_head_header_fields_t * p_fields = (memobj_head_header_fields_t *)&user_cnt;
if (p_fields->user_cnt == 0)
{
nrf_memobj_free(p_obj);
}
}
static void memobj_op(nrf_memobj_t * p_obj,
void * p_data,
uint32_t len,
uint32_t offset,
bool read)
{
memobj_head_t * p_head = (memobj_head_t *)p_obj;
uint32_t space_in_chunk = p_head->head_header.data.fields.chunk_size;
memobj_elem_t * p_curr_chunk = (memobj_elem_t *)p_obj;
uint32_t chunk_idx = (offset + sizeof(memobj_head_header_fields_t))/space_in_chunk;
uint32_t chunk_offset = (offset + sizeof(memobj_head_header_fields_t)) % space_in_chunk;
uint8_t chunks_expected = CEIL_DIV((offset + sizeof(memobj_head_header_fields_t) + len),
space_in_chunk);
UNUSED_VARIABLE(chunks_expected);
ASSERT(p_head->head_header.data.fields.chunk_cnt >= chunks_expected);
while (chunk_idx > 0)
{
p_curr_chunk = p_curr_chunk->header.p_next;
chunk_idx--;
}
uint32_t src_offset = 0;
uint32_t curr_cpy_size = space_in_chunk-chunk_offset;
curr_cpy_size = curr_cpy_size > len ? len : curr_cpy_size;
while (len)
{
if (read)
{
memcpy(&((uint8_t *)p_data)[src_offset], &p_curr_chunk->data[chunk_offset], curr_cpy_size);
}
else
{
memcpy(&p_curr_chunk->data[chunk_offset], &((uint8_t *)p_data)[src_offset], curr_cpy_size);
}
chunk_offset = 0;
p_curr_chunk = p_curr_chunk->header.p_next;
len -= curr_cpy_size;
src_offset += curr_cpy_size;
curr_cpy_size = (space_in_chunk > len) ? len : space_in_chunk;
}
}
void nrf_memobj_write(nrf_memobj_t * p_obj,
void * p_data,
uint32_t len,
uint32_t offset)
{
memobj_op(p_obj, p_data, len, offset, false);
}
void nrf_memobj_read(nrf_memobj_t * p_obj,
void * p_data,
uint32_t len,
uint32_t offset)
{
memobj_op(p_obj, p_data, len, offset, true);
}

View File

@ -0,0 +1,198 @@
/**
* 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.
*
*/
#ifndef NRF_MEMOBJ_H
#define NRF_MEMOBJ_H
/**
* @defgroup nrf_memobj Memory Object module
* @{
* @ingroup app_common
* @brief Functions for controlling memory object
*/
#include <stdint.h>
#include <stdlib.h>
#include "sdk_errors.h"
#include "nrf_balloc.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Memory object can consist of multiple object with the same size. Each object has header and data
* part. First element in memory object is memory object head which has special header, remaining objects
* has the same header. Model of memory object is presented below.
*
* |---------------------| |---------------------| |---------------------|
* | head header (u32): | --->| std header - p_next |------->| p_memobj_pool |
* | num_of_chunks, | | |---------------------| |---------------------|
* | ref counter | | | | | |
* |---------------------| | | | | |
* | std header - p_next |-| | | .... | |
* |---------------------| | data | | data |
* | | | | | |
* | data | | | | |
* | | | | | |
* |---------------------| |---------------------| |---------------------|
* head mid_element last_element
*
*
*/
#define NRF_MEMOBJ_STD_HEADER_SIZE sizeof(uint32_t)
/**
* @brief Macro for creating a nrf_memobj pool.
*
* Macro declares nrf_balloc object. Element in the pool contains user defined data part and
* memobj header.
*/
#define NRF_MEMOBJ_POOL_DEF(_name, _element_size, _pool_size) \
NRF_BALLOC_DEF(_name, ((_element_size)+NRF_MEMOBJ_STD_HEADER_SIZE), (_pool_size))
/**
* @brief Pool of memobj.
*/
typedef nrf_balloc_t nrf_memobj_pool_t;
/**
* @brief Memobj handle.
*/
typedef void * nrf_memobj_t;
/**
* @brief Function for initializing the memobj pool instance.
*
* This function initializes the pool.
*
* @param[in] p_pool Pointer to the memobj pool instance structure.
*
* @return NRF_SUCCESS on success, otherwise error code.
*/
ret_code_t nrf_memobj_pool_init(nrf_memobj_pool_t const * p_pool);
/**
* @brief Function for allocating memobj with requested size.
*
* Fixed length elements in the pool are linked together to provide amount of memory requested by
* the user. If memory object is successfully allocated then user can use memory however it is
* fragmented into multiple object so it has to be access through the API: @ref nrf_memobj_write,
* @ref nrf_memobj_read.
*
* This function initializes the pool.
*
* @param[in] p_pool Pointer to the memobj pool instance structure.
* @param[in] size Data size of requested object.
*
* @return Pointer to memory object or NULL if requested size cannot be allocated.
*/
nrf_memobj_t * nrf_memobj_alloc(nrf_memobj_pool_t const * p_pool,
size_t size);
/**
* @brief Function for indicating that memory object is used and cannot be freed.
*
* Memory object can be shared and reused between multiple modules and this mechanism ensures that
* object is freed when no longer used by any module. Memory object has a counter which is incremented
* whenever this function is called. @ref nrf_memobj_put function decrements the counter.
*
* @param[in] p_obj Pointer to memory object.
*/
void nrf_memobj_get(nrf_memobj_t const * p_obj);
/**
* @brief Function for indicated that memory object is no longer used by the module and can be freed
* if no other module is using it.
*
* Memory object is returned to the pool if internal counter reaches 0 after decrementing. It means
* that no other module is needing it anymore.
*
* @note Memory object holds pointer to the pool which was used to allocate it so it does not have
* to be provided explicitly to this function.
*
* @param[in] p_obj Pointer to memory object.
*/
void nrf_memobj_put(nrf_memobj_t * p_obj);
/**
* @brief Function for forcing freeing of the memory object.
*
* @note This function should be use with caution because it can lead to undefined behavior of the
* modules since modules using the memory object are not aware that it has been freed.
*
* @param[in] p_obj Pointer to memory object.
*/
void nrf_memobj_free(nrf_memobj_t * p_obj);
/**
* @brief Function for writing data to the memory object.
*
* @param[in] p_obj Pointer to memory object.
* @param[in] p_data Pointer to data to be written to the memory object.
* @param[in] len Amount of data to be written to the memory object.
* @param[in] offset Offset.
*/
void nrf_memobj_write(nrf_memobj_t * p_obj,
void * p_data,
uint32_t len,
uint32_t offset);
/**
* @brief Function for reading data from the memory object.
*
* @param[in] p_obj Pointer to memory object.
* @param[in] p_data Pointer to the destination buffer.
* @param[in] len Amount of data to be read from the memory object.
* @param[in] offset Offset.
*/
void nrf_memobj_read(nrf_memobj_t * p_obj,
void * p_data,
uint32_t len,
uint32_t offset);
#ifdef __cplusplus
}
#endif
#endif //NRF_MEMOBJ_H
/** @} */

View File

@ -0,0 +1,191 @@
/**
* 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.
*
*/
#ifndef NRF_SECTION_H__
#define NRF_SECTION_H__
#include "nordic_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup section_vars Section variables
* @ingroup app_common
* @{
*
* @brief Section variables.
*/
//lint -save -e27 -esym(526,*)
#if defined(__ICCARM__)
// Enable IAR language extensions
#pragma language=extended
#endif
/**@brief Macro for obtaining the address of the beginning of a section.
*
* param[in] section_name Name of the section.
* @hideinitializer
*/
#if defined(__CC_ARM)
#define NRF_SECTION_START_ADDR(section_name) &CONCAT_2(section_name, $$Base)
#elif defined(__GNUC__)
#define NRF_SECTION_START_ADDR(section_name) &CONCAT_2(__start_, section_name)
#elif defined(__ICCARM__)
#define NRF_SECTION_START_ADDR(section_name) __section_begin(STRINGIFY(section_name))
#endif
/**@brief Macro for obtaining the address of the end of a section.
*
* @param[in] section_name Name of the section.
* @hideinitializer
*/
#if defined(__CC_ARM)
#define NRF_SECTION_END_ADDR(section_name) &CONCAT_2(section_name, $$Limit)
#elif defined(__GNUC__)
#define NRF_SECTION_END_ADDR(section_name) &CONCAT_2(__stop_, section_name)
#elif defined(__ICCARM__)
#define NRF_SECTION_END_ADDR(section_name) __section_end(STRINGIFY(section_name))
#endif
/**@brief Macro for retrieving the length of a given section, in bytes.
*
* @param[in] section_name Name of the section.
* @hideinitializer
*/
#define NRF_SECTION_LENGTH(section_name) \
((size_t)NRF_SECTION_END_ADDR(section_name) - \
(size_t)NRF_SECTION_START_ADDR(section_name))
/**@brief Macro for creating a section.
*
* @param[in] section_name Name of the section.
* @param[in] data_type Data type of the variables to be registered in the section.
*
* @warning Data type must be word aligned to prevent padding.
* @hideinitializer
*/
#if defined(__CC_ARM)
#define NRF_SECTION_DEF(section_name, data_type) \
extern data_type * CONCAT_2(section_name, $$Base); \
extern void * CONCAT_2(section_name, $$Limit)
#elif defined(__GNUC__)
#define NRF_SECTION_DEF(section_name, data_type) \
extern data_type * CONCAT_2(__start_, section_name); \
extern void * CONCAT_2(__stop_, section_name)
#elif defined(__ICCARM__)
#define NRF_SECTION_DEF(section_name, data_type) \
_Pragma(STRINGIFY(section = STRINGIFY(section_name)));
#endif
/**@brief Macro for declaring a variable and registering it in a section.
*
* @details Declares a variable and registers it in a named section. This macro ensures that the
* variable is not stripped away when using optimizations.
*
* @note The order in which variables are placed in a section is dependent on the order in
* which the linker script encounters the variables during linking.
*
* @param[in] section_name Name of the section.
* @param[in] section_var Variable to register in the given section.
* @hideinitializer
*/
#if defined(__CC_ARM)
#define NRF_SECTION_ITEM_REGISTER(section_name, section_var) \
section_var __attribute__ ((section(STRINGIFY(section_name)))) __attribute__((used))
#elif defined(__GNUC__)
#define NRF_SECTION_ITEM_REGISTER(section_name, section_var) \
section_var __attribute__ ((section("." STRINGIFY(section_name)))) __attribute__((used))
#elif defined(__ICCARM__)
#define NRF_SECTION_ITEM_REGISTER(section_name, section_var) \
__root section_var @ STRINGIFY(section_name)
#endif
/**@brief Macro for retrieving a variable from a section.
*
* @warning The stored symbol can only be resolved using this macro if the
* type of the data is word aligned. The operation of acquiring
* the stored symbol relies on the size of the stored type. No
* padding can exist in the named section in between individual
* stored items or this macro will fail.
*
* @param[in] section_name Name of the section.
* @param[in] data_type Data type of the variable.
* @param[in] i Index of the variable in section.
* @hideinitializer
*/
#define NRF_SECTION_ITEM_GET(section_name, data_type, i) \
((data_type*)NRF_SECTION_START_ADDR(section_name) + (i))
/**@brief Macro for getting the number of variables in a section.
*
* @param[in] section_name Name of the section.
* @param[in] data_type Data type of the variables in the section.
* @hideinitializer
*/
#define NRF_SECTION_ITEM_COUNT(section_name, data_type) \
NRF_SECTION_LENGTH(section_name) / sizeof(data_type)
/** @} */
//lint -restore
#ifdef __cplusplus
}
#endif
#endif // NRF_SECTION_H__

View File

@ -0,0 +1,125 @@
/**
* 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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_SECTION_ITER)
#include "nrf_section_iter.h"
#if !defined(__GNUC__)
static void nrf_section_iter_item_set(nrf_section_iter_t * p_iter)
{
ASSERT(p_iter != NULL);
ASSERT(p_iter->p_set != NULL);
ASSERT(p_iter->p_section != NULL);
while (true)
{
if (p_iter->p_section == p_iter->p_set->p_last)
{
// End of the section set.
p_iter->p_item = NULL;
return;
}
if (p_iter->p_section->p_start != p_iter->p_section->p_end)
{
// Not empty section.
p_iter->p_item = p_iter->p_section->p_start;
return;
}
// Next section.
p_iter->p_section++;
}
}
#endif
void nrf_section_iter_init(nrf_section_iter_t * p_iter, nrf_section_set_t const * p_set)
{
ASSERT(p_iter != NULL);
ASSERT(p_set != NULL);
p_iter->p_set = p_set;
#if defined(__GNUC__)
p_iter->p_item = p_iter->p_set->section.p_start;
if (p_iter->p_item == p_iter->p_set->section.p_end)
{
p_iter->p_item = NULL;
}
#else
p_iter->p_section = p_set->p_first;
nrf_section_iter_item_set(p_iter);
#endif
}
void nrf_section_iter_next(nrf_section_iter_t * p_iter)
{
ASSERT(p_iter != NULL);
ASSERT(p_iter->p_set != NULL);
if (p_iter->p_item == NULL)
{
return;
}
p_iter->p_item = (void *)((size_t)(p_iter->p_item) + p_iter->p_set->item_size);
#if defined(__GNUC__)
if (p_iter->p_item == p_iter->p_set->section.p_end)
{
p_iter->p_item = NULL;
}
#else
ASSERT(p_iter->p_section != NULL);
// End of current section reached?
if (p_iter->p_item == p_iter->p_section->p_end)
{
p_iter->p_section++;
nrf_section_iter_item_set(p_iter);
}
#endif
}
#endif // NRF_MODULE_ENABLED(NRF_SECTION_ITER)

View File

@ -0,0 +1,206 @@
/**
* 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.
*
*/
#ifndef NRF_SECTION_ITER_H__
#define NRF_SECTION_ITER_H__
#include <stddef.h>
#include "nrf_section.h"
#include "nrf_assert.h"
#include "app_util.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup nrf_section_iter Section variables iterator
* @ingroup app_common
* @{
*/
/**@brief Single section description structure. */
typedef struct
{
void * p_start; //!< Pointer to the start of section.
void * p_end; //!< Pointer to the end of section.
} nrf_section_t;
/**@brief Set of the sections description structure. */
typedef struct
{
#if defined(__GNUC__)
nrf_section_t section; //!< Description of the set of sections.
/**<
* In case of GCC all sections in the set are sorted and
* placed in contiguous area, because they are treated as
* one section.
*/
#else
nrf_section_t const * p_first; //!< Pointer to the first section in the set.
nrf_section_t const * p_last; //!< Pointer to the last section in the set.
#endif
size_t item_size; //!< Size of the single item in the section.
} nrf_section_set_t;
/**@brief Section iterator structure. */
typedef struct
{
nrf_section_set_t const * p_set; //!< Pointer to the appropriate section set.
#if !defined(__GNUC__)
nrf_section_t const * p_section; //!< Pointer to the selected section.
/**<
* In case of GCC all sections in the set are sorted and
* placed in contiguous area, because they are treated
* as one section.
*/
#endif
void * p_item; //!< Pointer to the selected item in the section.
} nrf_section_iter_t;
/**@brief Create a set of sections.
*
* @note This macro reserves memory for the given set of sections.
*
* @details A set of sections, is an ordered collections of sections.
*
* @param[in] _name Name of the set.
* @param[in] _type Type of the elements stored in the sections.
* @param[in] _count Number of the sections in the set. This parameter is ignored in case of GCC.
* @hideinitializer
*/
#if defined(__GNUC__)
#define NRF_SECTION_SET_DEF(_name, _type, _count) \
\
NRF_SECTION_DEF(_name, _type); \
static nrf_section_set_t const _name = \
{ \
.section = \
{ \
.p_start = NRF_SECTION_START_ADDR(_name), \
.p_end = NRF_SECTION_END_ADDR(_name), \
}, \
.item_size = sizeof(_type), \
}
#else
#define NRF_SECTION_SET_DEF(_name, _type, _count) \
/*lint -save -emacro(14, MACRO_REPEAT_FOR*) */ \
MACRO_REPEAT_FOR(_count, NRF_SECTION_DEF_, _name, _type) \
static nrf_section_t const CONCAT_2(_name, _array)[] = \
{ \
MACRO_REPEAT_FOR(_count, NRF_SECTION_SET_DEF_, _name) \
}; \
/*lint -restore */ \
static nrf_section_set_t const _name = \
{ \
.p_first = CONCAT_2(_name, _array), \
.p_last = CONCAT_2(_name, _array) + ARRAY_SIZE(CONCAT_2(_name, _array)), \
.item_size = sizeof(_type), \
}
#ifndef DOXYGEN
#define NRF_SECTION_DEF_(_priority, _name, _type) \
NRF_SECTION_DEF(CONCAT_2(_name, _priority), _type);
#define NRF_SECTION_SET_DEF_(_priority, _name) \
{ \
.p_start = NRF_SECTION_START_ADDR(CONCAT_2(_name, _priority)), \
.p_end = NRF_SECTION_END_ADDR(CONCAT_2(_name, _priority)), \
},
#endif // DOXYGEN
#endif // __GNUC__
/**@brief Macro to declare a variable and register it in the section set.
*
* @note The order of the section in the set is based on the priority. The order with which
* variables are placed in a section is dependant on the order with which the linker
* encouters the variables during linking.
*
* @param[in] _name Name of the section set.
* @param[in] _priority Priority of the desired section.
* @param[in] _var The variable to register in the given section.
* @hideinitializer
*/
#define NRF_SECTION_SET_ITEM_REGISTER(_name, _priority, _var) \
NRF_SECTION_ITEM_REGISTER(CONCAT_2(_name, _priority), _var)
/**@brief Function for initializing the section set iterator.
*
* @param[in] p_iter Pointer to the iterator.
* @param[in] p_set Pointer to the sections set.
*/
void nrf_section_iter_init(nrf_section_iter_t * p_iter, nrf_section_set_t const * p_set);
/**@brief Function for incrementing iterator.
*
* @param[in] p_iter Pointer to the iterator.
*/
void nrf_section_iter_next(nrf_section_iter_t * p_iter);
/**@brief Function for getting the element pointed to by the iterator.
*
* @param[in] p_iter Pointer to the iterator.
*
* @retval Pointer to the element or NULL if iterator points end of the set.
*/
static inline void * nrf_section_iter_get(nrf_section_iter_t const * p_iter)
{
ASSERT(p_iter);
return p_iter->p_item;
}
/** @} */
#ifdef __cplusplus
}
#endif
#endif // NRF_SECTION_ITER_H__

View File

@ -0,0 +1,244 @@
/**
* 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 "sdk_config.h"
#if NRF_FSTORAGE_ENABLED
#include "nrf_fstorage.h"
#include <stddef.h>
#include <stdint.h>
#include "sdk_errors.h"
#include "sdk_macros.h"
#include "nrf_section.h"
#define NRF_LOG_MODULE_NAME nrf_fstorage
#include "nrf_log.h"
NRF_LOG_MODULE_REGISTER();
/* Create the section "fs_data". */
NRF_SECTION_DEF(fs_data, nrf_fstorage_t);
/**@brief Macro to handle user input validation.
*
* If @p _cond evaluates to true, does nothing. Otherwise,
* if the NRF_FSTORAGE_PARAM_CHECK_DISABLED is not set, logs an error message and returns @p _err.
* If the NRF_FSTORAGE_PARAM_CHECK_DISABLED is set, behaves like the @ref ASSERT macro.
*
* Parameter checking implemented using this macro can be optionally turned off for release code.
* Only disable runtime parameter checks if size if a major concern.
*
* @param _cond The condition to be evaluated.
* @param _err The error code to be returned.
*/
#define NRF_FSTORAGE_PARAM_CHECK(_cond, _err) \
NRF_PARAM_CHECK(NRF_FSTORAGE, _cond, _err, NRF_LOG_ERROR)
static bool addr_is_aligned32(uint32_t addr);
static bool addr_is_page_aligned(nrf_fstorage_t const * p_fs, uint32_t addr);
static bool addr_is_within_bounds(nrf_fstorage_t const * p_fs, uint32_t addr, uint32_t len);
ret_code_t nrf_fstorage_init(nrf_fstorage_t * p_fs,
nrf_fstorage_api_t * p_api,
void * p_param)
{
NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL);
NRF_FSTORAGE_PARAM_CHECK(p_api, NRF_ERROR_NULL);
p_fs->p_api = p_api;
return (p_fs->p_api)->init(p_fs, p_param);
}
ret_code_t nrf_fstorage_uninit(nrf_fstorage_t * p_fs,
void * p_param)
{
ret_code_t rc;
NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL);
NRF_FSTORAGE_PARAM_CHECK(p_fs->p_api, NRF_ERROR_INVALID_STATE);
rc = (p_fs->p_api)->uninit(p_fs, p_param);
/* Uninitialize the API. */
p_fs->p_api = NULL;
p_fs->p_flash_info = NULL;
return rc;
}
ret_code_t nrf_fstorage_read(nrf_fstorage_t const * p_fs,
uint32_t src,
void * p_dest,
uint32_t len)
{
NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL);
NRF_FSTORAGE_PARAM_CHECK(p_dest, NRF_ERROR_NULL);
NRF_FSTORAGE_PARAM_CHECK(p_fs->p_api, NRF_ERROR_INVALID_STATE);
NRF_FSTORAGE_PARAM_CHECK(len, NRF_ERROR_INVALID_LENGTH);
/* Source addres must be word-aligned. */
NRF_FSTORAGE_PARAM_CHECK(addr_is_aligned32(src), NRF_ERROR_INVALID_ADDR);
NRF_FSTORAGE_PARAM_CHECK(addr_is_within_bounds(p_fs, src, len), NRF_ERROR_INVALID_ADDR);
return (p_fs->p_api)->read(p_fs, src, p_dest, len);
}
ret_code_t nrf_fstorage_write(nrf_fstorage_t const * p_fs,
uint32_t dest,
void const * p_src,
uint32_t len,
void * p_context)
{
NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL);
NRF_FSTORAGE_PARAM_CHECK(p_src, NRF_ERROR_NULL);
NRF_FSTORAGE_PARAM_CHECK(p_fs->p_api, NRF_ERROR_INVALID_STATE);
NRF_FSTORAGE_PARAM_CHECK(len, NRF_ERROR_INVALID_LENGTH);
/* Length must be a multiple of the program unit. */
NRF_FSTORAGE_PARAM_CHECK(!(len % p_fs->p_flash_info->program_unit), NRF_ERROR_INVALID_LENGTH);
/* Source and destination addresses must be word-aligned. */
NRF_FSTORAGE_PARAM_CHECK(addr_is_aligned32(dest), NRF_ERROR_INVALID_ADDR);
NRF_FSTORAGE_PARAM_CHECK(addr_is_aligned32((uint32_t)p_src), NRF_ERROR_INVALID_ADDR);
NRF_FSTORAGE_PARAM_CHECK(addr_is_within_bounds(p_fs, dest, len), NRF_ERROR_INVALID_ADDR);
return (p_fs->p_api)->write(p_fs, dest, p_src, len, p_context);
}
ret_code_t nrf_fstorage_erase(nrf_fstorage_t const * p_fs,
uint32_t page_addr,
uint32_t len,
void * p_context)
{
NRF_FSTORAGE_PARAM_CHECK(p_fs, NRF_ERROR_NULL);
NRF_FSTORAGE_PARAM_CHECK(p_fs->p_api, NRF_ERROR_INVALID_STATE);
NRF_FSTORAGE_PARAM_CHECK(len, NRF_ERROR_INVALID_LENGTH);
/* Address must be aligned to a page boundary. */
NRF_FSTORAGE_PARAM_CHECK(addr_is_page_aligned(p_fs, page_addr), NRF_ERROR_INVALID_ADDR);
NRF_FSTORAGE_PARAM_CHECK(
addr_is_within_bounds(p_fs, page_addr, (len * p_fs->p_flash_info->erase_unit)),
NRF_ERROR_INVALID_ADDR
);
return (p_fs->p_api)->erase(p_fs, page_addr, len, p_context);
}
uint8_t const * nrf_fstorage_rmap(nrf_fstorage_t const * p_fs, uint32_t addr)
{
if ((p_fs == NULL) || (p_fs->p_api == NULL))
{
return NULL;
}
return (p_fs->p_api)->rmap(p_fs, addr);
}
uint8_t * nrf_fstorage_wmap(nrf_fstorage_t const * p_fs, uint32_t addr)
{
if ((p_fs == NULL) || (p_fs->p_api == NULL))
{
return NULL;
}
return (p_fs->p_api)->wmap(p_fs, addr);
}
bool nrf_fstorage_is_busy(nrf_fstorage_t const * p_fs)
{
/* If a NULL instance is provided, return true if any instance is busy.
* Uninitialized instances are considered not busy. */
if ((p_fs == NULL) || (p_fs->p_api == NULL))
{
for (uint32_t i = 0; i < NRF_FSTORAGE_INSTANCE_CNT; i++)
{
p_fs = NRF_FSTORAGE_INSTANCE_GET(i); /* cannot be NULL. */
if (p_fs->p_api != NULL)
{
/* p_api->is_busy() cannot be NULL. */
if (p_fs->p_api->is_busy(p_fs))
{
return true;
}
}
}
return false;
}
return p_fs->p_api->is_busy(p_fs);
}
static bool addr_is_within_bounds(nrf_fstorage_t const * p_fs,
uint32_t addr,
uint32_t len)
{
return ( (addr >= p_fs->start_addr)
&& (addr + len - 1 <= p_fs->end_addr));
}
static bool addr_is_aligned32(uint32_t addr)
{
return !(addr & 0x03);
}
static bool addr_is_page_aligned(nrf_fstorage_t const * p_fs,
uint32_t addr)
{
return (addr & (p_fs->p_flash_info->erase_unit - 1)) == 0;
}
#endif // NRF_FSTORAGE_ENABLED

View File

@ -0,0 +1,341 @@
/**
* 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.
*
*/
#ifndef NRF_FSTORAGE_H__
#define NRF_FSTORAGE_H__
/**
* @file
*
* @defgroup nrf_fstorage Flash storage (fstorage)
* @ingroup app_common
* @{
*
* @brief Flash abstraction library that provides basic read, write, and erase operations.
*
* @details The fstorage library can be implemented in different ways. Two implementations are provided:
* - The @ref nrf_fstorage_sd implements flash access through the SoftDevice.
* - The @ref nrf_fstorage_nvmc implements flash access through the non-volatile memory controller.
*
* You can select the implementation that should be used independently for each instance of fstorage.
*/
#include <stdint.h>
#include <stdbool.h>
#include "sdk_errors.h"
#include "nrf_section.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@brief Macro for defining an fstorage instance.
*
* Users of fstorage must define an instance variable by using this macro.
* Each instance is tied to an API implementation and contains information such
* as the program and erase units for the target flash peripheral.
* Instance variables are placed in the "fs_data" section of the binary.
*
* @param[in] inst A definition of an @ref nrf_fstorage_t variable.
*/
#define NRF_FSTORAGE_DEF(inst) NRF_SECTION_ITEM_REGISTER(fs_data, inst)
/**@brief Macro for retrieving an fstorage instance. */
#define NRF_FSTORAGE_INSTANCE_GET(i) NRF_SECTION_ITEM_GET(fs_data, nrf_fstorage_t, (i))
/**@brief Macro for retrieving the total number of fstorage instances. */
#define NRF_FSTORAGE_INSTANCE_CNT NRF_SECTION_ITEM_COUNT(fs_data, nrf_fstorage_t)
/**@brief Event IDs. */
typedef enum
{
NRF_FSTORAGE_EVT_READ_RESULT,
NRF_FSTORAGE_EVT_WRITE_RESULT, //!< Event for @ref nrf_fstorage_write.
NRF_FSTORAGE_EVT_ERASE_RESULT //!< Event for @ref nrf_fstorage_erase.
} nrf_fstorage_evt_id_t;
/**@brief An fstorage event. */
typedef struct
{
nrf_fstorage_evt_id_t id; //!< The event ID.
ret_code_t result; //!< Result of the operation.
uint32_t addr; //!< Address at which the operation was performed.
void const * p_src; //!< Buffer written to flash.
uint32_t len; //!< Length of the operation.
void * p_param; //!< User-defined parameter passed to the event handler.
} nrf_fstorage_evt_t;
/**@brief Event handler function prototype.
*
* @param[in] p_evt The event.
*/
typedef void (*nrf_fstorage_evt_handler_t)(nrf_fstorage_evt_t * p_evt);
/**@brief Information about the implementation and the flash peripheral. */
typedef struct
{
uint32_t erase_unit; //!< Size of a flash page (in bytes). A flash page is the smallest unit that can be erased.
uint32_t program_unit; //!< Size of the smallest programmable unit (in bytes).
bool rmap; //!< The device address space is memory mapped to the MCU address space.
bool wmap; //!< The device address space is memory mapped to a writable MCU address space.
} const nrf_fstorage_info_t;
/* Necessary forward declaration. */
struct nrf_fstorage_api_s;
/**@brief An fstorage instance.
*
* @details Use the @ref NRF_FSTORAGE_DEF macro to define an fstorage instance.
*
* An instance is tied to an API implementation and contains information about the flash device,
* such as the program and erase units as well and implementation-specific functionality.
*/
typedef struct
{
/**@brief The API implementation used by this instance. */
struct nrf_fstorage_api_s const * p_api;
/**@brief Information about the implementation functionality and the flash peripheral. */
nrf_fstorage_info_t * p_flash_info;
/**@brief The event handler function.
*
* If set to NULL, no events will be sent.
*/
nrf_fstorage_evt_handler_t evt_handler;
/**@brief The beginning of the flash space on which this fstorage instance should operate.
* All flash operations must be within the address specified in
* this field and @ref end_addr.
*
* This field must be set manually.
*/
uint32_t start_addr;
/**@brief The last address (exclusive) of flash on which this fstorage instance should operate.
* All flash operations must be within the address specified in
* this field and @ref start_addr.
*
* This field must be set manually.
*/
uint32_t end_addr;
} nrf_fstorage_t;
/**@brief Functions provided by the API implementation. */
typedef struct nrf_fstorage_api_s
{
/**@brief Initialize the flash peripheral. */
ret_code_t (*init)(nrf_fstorage_t * p_fs, void * p_param);
/**@brief Uninitialize the flash peripheral. */
ret_code_t (*uninit)(nrf_fstorage_t * p_fs, void * p_param);
/**@brief Read data from flash. */
ret_code_t (*read)(nrf_fstorage_t const * p_fs, uint32_t src, void * p_dest, uint32_t len);
/**@brief Write bytes to flash. */
ret_code_t (*write)(nrf_fstorage_t const * p_fs, uint32_t dest, void const * p_src, uint32_t len, void * p_param);
/**@brief Erase flash pages. */
ret_code_t (*erase)(nrf_fstorage_t const * p_fs, uint32_t addr, uint32_t len, void * p_param);
/**@brief Map a device address to a readable address within the MCU address space. */
uint8_t const * (*rmap)(nrf_fstorage_t const * p_fs, uint32_t addr);
/**@brief Map a device address to a writable address within the MCU address space. */
uint8_t * (*wmap)(nrf_fstorage_t const * p_fs, uint32_t addr);
/**@brief Check if there are any pending flash operations. */
bool (*is_busy)(nrf_fstorage_t const * p_fs);
} const nrf_fstorage_api_t;
/**@brief Function for initializing fstorage.
*
* @param[in] p_fs The fstorage instance to initialize.
* @param[in] p_api The API implementation to use.
* @param[in] p_param An optional parameter to pass to the implementation-specific API call.
*
* @retval NRF_SUCCESS If initialization was successful.
* @retval NRF_ERROR_NULL If @p p_fs or @p p_api field in @p p_fs is NULL.
* @retval NRF_ERROR_INTERNAL If another error occurred.
*/
ret_code_t nrf_fstorage_init(nrf_fstorage_t * p_fs,
nrf_fstorage_api_t * p_api,
void * p_param);
/**@brief Function for uninitializing an fstorage instance.
*
* @param[in] p_fs The fstorage instance to uninitialize.
* @param[in] p_param An optional parameter to pass to the implementation-specific API call.
*
* @retval NRF_SUCCESS If uninitialization was successful.
* @retval NRF_ERROR_NULL If @p p_fs is NULL.
* @retval NRF_ERROR_INVALID_STATE If the module is not initialized.
* @retval NRF_ERROR_INTERNAL If another error occurred.
*/
ret_code_t nrf_fstorage_uninit(nrf_fstorage_t * p_fs, void * p_param);
/**@brief Function for reading data from flash.
*
* Copy @p len bytes from @p addr to @p p_dest.
*
* @param[in] p_fs The fstorage instance.
* @param[in] addr Address in flash where to read from.
* @param[in] p_dest Buffer where the data should be copied.
* @param[in] len Length of the data to be copied (in bytes).
*
* @retval NRF_SUCCESS If the operation was successful.
* @retval NRF_ERROR_NULL If @p p_fs or @p p_dest is NULL.
* @retval NRF_ERROR_INVALID_STATE If the module is not initialized.
* @retval NRF_ERROR_INVALID_LENGTH If @p len is zero or otherwise invalid.
* @retval NRF_ERROR_INVALID_ADDR If the address @p addr is outside the flash memory
* boundaries specified in @p p_fs, or if it is unaligned.
*/
ret_code_t nrf_fstorage_read(nrf_fstorage_t const * p_fs,
uint32_t addr,
void * p_dest,
uint32_t len);
/**@brief Function for writing data to flash.
*
* Write @p len bytes from @p p_src to @p dest.
*
* When using @ref nrf_fstorage_sd, the data is written by several calls to @ref sd_flash_write if
* the length of the data exceeds @ref NRF_FSTORAGE_SD_MAX_WRITE_SIZE bytes.
* Only one event is sent upon completion.
*
* @note The data to be written to flash must be kept in memory until the operation has
* terminated and an event is received.
*
* @param[in] p_fs The fstorage instance.
* @param[in] dest Address in flash memory where to write the data.
* @param[in] p_src Data to be written.
* @param[in] len Length of the data (in bytes).
* @param[in] p_param User-defined parameter passed to the event handler (may be NULL).
*
* @retval NRF_SUCCESS If the operation was accepted.
* @retval NRF_ERROR_NULL If @p p_fs or @p p_src is NULL.
* @retval NRF_ERROR_INVALID_STATE If the module is not initialized.
* @retval NRF_ERROR_INVALID_LENGTH If @p len is zero or not a multiple of the program unit,
* or if it is otherwise invalid.
* @retval NRF_ERROR_INVALID_ADDR If the address @p dest is outside the flash memory
* boundaries specified in @p p_fs, or if it is unaligned.
* @retval NRF_ERROR_NO_MEM If no memory is available to accept the operation.
* When using the @ref nrf_fstorage_sd, this error
* indicates that the internal queue of operations is full.
*/
ret_code_t nrf_fstorage_write(nrf_fstorage_t const * p_fs,
uint32_t dest,
void const * p_src,
uint32_t len,
void * p_param);
/**@brief Function for erasing flash pages.
*
* @details This function erases @p len pages starting from the page at address @p page_addr.
* The erase operation must be initiated on a page boundary.
*
* @param[in] p_fs The fstorage instance.
* @param[in] page_addr Address of the page to erase.
* @param[in] len Number of pages to erase.
* @param[in] p_param User-defined parameter passed to the event handler (may be NULL).
*
* @retval NRF_SUCCESS If the operation was accepted.
* @retval NRF_ERROR_NULL If @p p_fs is NULL.
* @retval NRF_ERROR_INVALID_STATE If the module is not initialized.
* @retval NRF_ERROR_INVALID_LENGTH If @p len is zero.
* @retval NRF_ERROR_INVALID_ADDR If the address @p page_addr is outside the flash memory
* boundaries specified in @p p_fs, or if it is unaligned.
* @retval NRF_ERROR_NO_MEM If no memory is available to accept the operation.
* When using the @ref nrf_fstorage_sd, this error
* indicates that the internal queue of operations is full.
*/
ret_code_t nrf_fstorage_erase(nrf_fstorage_t const * p_fs,
uint32_t page_addr,
uint32_t len,
void * p_param);
/**@brief Map a flash address to a pointer in the MCU address space that can be dereferenced.
*
* @param p_fs The fstorage instance.
* @param addr The address to map.
*
* @retval A pointer to the specified address,
* or @c NULL if the address cannot be mapped or if @p p_fs is @c NULL.
*/
uint8_t const * nrf_fstorage_rmap(nrf_fstorage_t const * p_fs, uint32_t addr);
/**@brief Map a flash address to a pointer in the MCU address space that can be written to.
*
* @param p_fs The fstorage instance.
* @param addr The address to map.
*
* @retval A pointer to the specified address,
* or @c NULL if the address cannot be mapped or if @p p_fs is @c NULL.
*/
uint8_t * nrf_fstorage_wmap(nrf_fstorage_t const * p_fs, uint32_t addr);
/**@brief Function for querying the status of fstorage.
*
* @details An uninitialized instance of fstorage is treated as not busy.
*
* @param[in] p_fs The fstorage instance. Pass NULL to query all instances.
*
* @returns If @p p_fs is @c NULL, this function returns true if any fstorage instance is busy or false otherwise.
* @returns If @p p_fs is not @c NULL, this function returns true if the fstorage instance is busy or false otherwise.
*/
bool nrf_fstorage_is_busy(nrf_fstorage_t const * p_fs);
/** @} */
#ifdef __cplusplus
}
#endif
#endif // NRF_FSTORAGE_H__

View File

@ -0,0 +1,217 @@
/**
* 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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_FSTORAGE)
#include "nrf_fstorage_nvmc.h"
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include "nrf_nvmc.h"
#include "nrf_atomic.h"
static nrf_fstorage_info_t m_flash_info =
{
#if defined(NRF51)
.erase_unit = 1024,
#elif defined(NRF52_SERIES)
.erase_unit = 4096,
#endif
.program_unit = 4,
.rmap = true,
.wmap = false,
};
/* An operation initiated by fstorage is ongoing. */
static nrf_atomic_flag_t m_flash_operation_ongoing;
/* Send event to the event handler. */
static void event_send(nrf_fstorage_t const * p_fs,
nrf_fstorage_evt_id_t evt_id,
void const * p_src,
uint32_t addr,
uint32_t len,
void * p_param)
{
if (p_fs->evt_handler == NULL)
{
/* Nothing to do. */
return;
}
nrf_fstorage_evt_t evt =
{
.result = NRF_SUCCESS,
.id = evt_id,
.addr = addr,
.p_src = p_src,
.len = len,
.p_param = p_param,
};
p_fs->evt_handler(&evt);
}
static ret_code_t init(nrf_fstorage_t * p_fs, void * p_param)
{
UNUSED_PARAMETER(p_param);
p_fs->p_flash_info = &m_flash_info;
return NRF_SUCCESS;
}
static ret_code_t uninit(nrf_fstorage_t * p_fs, void * p_param)
{
UNUSED_PARAMETER(p_fs);
UNUSED_PARAMETER(p_param);
(void) nrf_atomic_flag_clear(&m_flash_operation_ongoing);
return NRF_SUCCESS;
}
static ret_code_t read(nrf_fstorage_t const * p_fs, uint32_t src, void * p_dest, uint32_t len)
{
UNUSED_PARAMETER(p_fs);
memcpy(p_dest, (uint32_t*)src, len);
return NRF_SUCCESS;
}
static ret_code_t write(nrf_fstorage_t const * p_fs,
uint32_t dest,
void const * p_src,
uint32_t len,
void * p_param)
{
if (nrf_atomic_flag_set_fetch(&m_flash_operation_ongoing))
{
return NRF_ERROR_BUSY;
}
nrf_nvmc_write_words(dest, (uint32_t*)p_src, (len / m_flash_info.program_unit));
/* Clear the flag before sending the event, to allow API calls in the event context. */
(void) nrf_atomic_flag_clear(&m_flash_operation_ongoing);
event_send(p_fs, NRF_FSTORAGE_EVT_WRITE_RESULT, p_src, dest, len, p_param);
return NRF_SUCCESS;
}
static ret_code_t erase(nrf_fstorage_t const * p_fs,
uint32_t page_addr,
uint32_t len,
void * p_param)
{
uint32_t progress = 0;
if (nrf_atomic_flag_set_fetch(&m_flash_operation_ongoing))
{
return NRF_ERROR_BUSY;
}
while (progress != len)
{
nrf_nvmc_page_erase(page_addr + (progress * m_flash_info.erase_unit));
progress++;
}
/* Clear the flag before sending the event, to allow API calls in the event context. */
(void) nrf_atomic_flag_clear(&m_flash_operation_ongoing);
event_send(p_fs, NRF_FSTORAGE_EVT_ERASE_RESULT, NULL, page_addr, len, p_param);
return NRF_SUCCESS;
}
static uint8_t const * rmap(nrf_fstorage_t const * p_fs, uint32_t addr)
{
UNUSED_PARAMETER(p_fs);
return (uint8_t*)addr;
}
static uint8_t * wmap(nrf_fstorage_t const * p_fs, uint32_t addr)
{
UNUSED_PARAMETER(p_fs);
UNUSED_PARAMETER(addr);
/* Not supported. */
return NULL;
}
static bool is_busy(nrf_fstorage_t const * p_fs)
{
UNUSED_PARAMETER(p_fs);
return m_flash_operation_ongoing;
}
/* The exported API. */
nrf_fstorage_api_t nrf_fstorage_nvmc =
{
.init = init,
.uninit = uninit,
.read = read,
.write = write,
.erase = erase,
.rmap = rmap,
.wmap = wmap,
.is_busy = is_busy
};
#endif // NRF_FSTORAGE_ENABLED

View File

@ -0,0 +1,75 @@
/**
* 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_fstorage_nvmc NVMC implementation
* @ingroup nrf_fstorage
* @{
*
* @brief API implementation of fstorage that uses the non-volatile memory controller (NVMC).
*/
#ifndef NRF_FSTORAGE_NVMC_H__
#define NRF_FSTORAGE_NVMC_H__
#include "nrf_fstorage.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@brief API implementation that uses the non-volatile memory controller.
*
* @details An fstorage instance with this API implementation can be initialized by providing
* this structure as a parameter to @ref nrf_fstorage_init.
* The structure is defined in @c nrf_fstorage_nvmc.c.
*/
extern nrf_fstorage_api_t nrf_fstorage_nvmc;
#ifdef __cplusplus
}
#endif
#endif // NRF_FSTORAGE_NVMC_H__
/** @} */

View File

@ -0,0 +1,624 @@
/**
* 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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_FSTORAGE)
#include "nrf_fstorage_sd.h"
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include "nordic_common.h"
#include "nrf_soc.h"
#include "nrf_sdh.h"
#include "nrf_sdh_soc.h"
#include "nrf_atomic.h"
#include "nrf_atfifo.h"
#include "app_util_platform.h"
#if (NRF_FSTORAGE_SD_MAX_WRITE_SIZE % 4)
#error NRF_FSTORAGE_SD_MAX_WRITE_SIZE must be a multiple of the word size.
#endif
/**@brief fstorage operation codes. */
typedef enum
{
NRF_FSTORAGE_OP_WRITE, //!< Write bytes to flash.
NRF_FSTORAGE_OP_ERASE //!< Erase flash pages.
} nrf_fstorage_sd_opcode_t;
ANON_UNIONS_ENABLE;
/**@brief fstorage operation queue element. */
typedef struct
{
nrf_fstorage_t const * p_fs; //!< The fstorage instance that requested the operation.
nrf_fstorage_sd_opcode_t op_code; //!< Requested operation.
void * p_param; //!< User-defined parameter passed to the event handler.
union
{
struct
{
void const * p_src; //!< Data to be written to flash.
uint32_t dest; //!< Destination of the data in flash.
uint32_t len; //!< Length of the data to be written (in bytes).
uint32_t offset; //!< Write offset.
} write;
struct
{
uint32_t page; //!< Physical page number.
uint32_t progress; //!< Number of pages erased.
uint32_t pages_to_erase; //!< Total number of pages to erase.
} erase;
};
} nrf_fstorage_sd_op_t;
ANON_UNIONS_DISABLE;
typedef enum
{
NRF_FSTORAGE_STATE_IDLE, //!< No operations requested to the SoftDevice.
NRF_FSTORAGE_STATE_OP_PENDING, //!< A non-fstorage operation is pending.
NRF_FSTORAGE_STATE_OP_EXECUTING, //!< An fstorage operation is executing.
} nrf_fstorage_sd_state_t;
/**@brief Internal state. */
typedef struct
{
nrf_atomic_flag_t initialized; //!< fstorage is initalized.
nrf_atomic_flag_t queue_running; //!< The queue is running.
/** Prevent API calls from entering queue_process(). */
nrf_fstorage_sd_state_t state; //!< Internal fstorage state.
uint32_t retries; //!< Number of times an operation has been retried on timeout.
bool sd_enabled; //!< The SoftDevice is enabled.
bool paused; //!< A SoftDevice state change is impending.
/** Do not load a new operation when the last one completes. */
} nrf_fstorage_sd_work_t;
void nrf_fstorage_sys_evt_handler(uint32_t, void *);
bool nrf_fstorage_sdh_req_handler(nrf_sdh_req_evt_t, void *);
void nrf_fstorage_sdh_state_handler(nrf_sdh_state_evt_t, void *);
/* Flash device information. */
static nrf_fstorage_info_t m_flash_info =
{
#if defined(NRF51)
.erase_unit = 1024,
#elif defined(NRF52_SERIES)
.erase_unit = 4096,
#endif
.program_unit = 4,
.rmap = true,
.wmap = false,
};
/* Queue of fstorage operations. */
NRF_ATFIFO_DEF(m_fifo, nrf_fstorage_sd_op_t, NRF_FSTORAGE_SD_QUEUE_SIZE);
/* Define a nrf_sdh_soc event observer to receive SoftDevice system events. */
NRF_SDH_SOC_OBSERVER(m_sys_obs, 0, nrf_fstorage_sys_evt_handler, NULL);
/* nrf_sdh request observer. */
NRF_SDH_REQUEST_OBSERVER(m_req_obs, 0) =
{
.handler = nrf_fstorage_sdh_req_handler,
};
/* nrf_sdh state observer. */
NRF_SDH_STATE_OBSERVER(m_state_obs, 0) =
{
.handler = nrf_fstorage_sdh_state_handler,
};
static nrf_fstorage_sd_work_t m_flags; /* Internal status. */
static nrf_fstorage_sd_op_t * m_p_cur_op; /* The current operation being executed. */
static nrf_atfifo_item_get_t m_iget_ctx; /* Context for nrf_atfifo_item_get() and nrf_atfifo_item_free(). */
/* Send events to the application. */
static void event_send(nrf_fstorage_sd_op_t const * p_op, ret_code_t result)
{
if (p_op->p_fs->evt_handler == NULL)
{
/* Nothing to do. */
return;
}
nrf_fstorage_evt_t evt =
{
.result = result,
.p_param = p_op->p_param,
};
switch (p_op->op_code)
{
case NRF_FSTORAGE_OP_WRITE:
evt.id = NRF_FSTORAGE_EVT_WRITE_RESULT;
evt.addr = p_op->write.dest;
evt.p_src = p_op->write.p_src;
evt.len = p_op->write.len;
break;
case NRF_FSTORAGE_OP_ERASE:
evt.id = NRF_FSTORAGE_EVT_ERASE_RESULT;
evt.addr = (p_op->erase.page * m_flash_info.erase_unit);
evt.len = p_op->erase.pages_to_erase;
break;
default:
/* Should not happen. */
break;
}
p_op->p_fs->evt_handler(&evt);
}
/* Write to flash. */
static uint32_t write_execute(nrf_fstorage_sd_op_t const * p_op)
{
uint32_t chunk_len;
chunk_len = MIN(p_op->write.len - p_op->write.offset, NRF_FSTORAGE_SD_MAX_WRITE_SIZE);
chunk_len = MAX(1, chunk_len / m_flash_info.program_unit);
/* Cast to p_src to uint32_t to perform arithmetic. */
uint32_t * p_dest = (uint32_t*)(p_op->write.dest + p_op->write.offset);
uint32_t const * p_src = (uint32_t*)((uint32_t)p_op->write.p_src + p_op->write.offset);
return sd_flash_write(p_dest, p_src, chunk_len);
}
/* Erase flash page(s). */
static uint32_t erase_execute(nrf_fstorage_sd_op_t const * p_op)
{
return sd_flash_page_erase(p_op->erase.page + p_op->erase.progress);
}
/* Free the current queue element. */
static void queue_free(void)
{
(void) nrf_atfifo_item_free(m_fifo, &m_iget_ctx);
}
/* Load a new operation from the queue. */
static bool queue_load_next(void)
{
m_p_cur_op = nrf_atfifo_item_get(m_fifo, &m_iget_ctx);
return (m_p_cur_op != NULL);
}
/* Execute an operation in the queue. */
static void queue_process(void)
{
uint32_t rc;
if (m_flags.state == NRF_FSTORAGE_STATE_IDLE)
{
if (!queue_load_next())
{
/* No more operations, nothing to do. */
m_flags.queue_running = false;
return;
}
}
m_flags.state = NRF_FSTORAGE_STATE_OP_EXECUTING;
switch (m_p_cur_op->op_code)
{
case NRF_FSTORAGE_OP_WRITE:
rc = write_execute(m_p_cur_op);
break;
case NRF_FSTORAGE_OP_ERASE:
rc = erase_execute(m_p_cur_op);
break;
default:
rc = NRF_ERROR_INTERNAL;
break;
}
switch (rc)
{
case NRF_SUCCESS:
{
/* The operation was accepted by the SoftDevice.
* If the SoftDevice is enabled, wait for a system event. Otherwise,
* the SoftDevice call is synchronous and will not send an event so we simulate it. */
if (!m_flags.sd_enabled)
{
nrf_fstorage_sys_evt_handler(NRF_EVT_FLASH_OPERATION_SUCCESS, NULL);
}
} break;
case NRF_ERROR_BUSY:
{
/* The SoftDevice is executing a flash operation that was not requested by fstorage.
* Stop processing the queue until a system event is received. */
m_flags.state = NRF_FSTORAGE_STATE_OP_PENDING;
} break;
default:
{
/* An error has occurred. We cannot proceed further with this operation. */
event_send(m_p_cur_op, NRF_ERROR_INTERNAL);
/* Reset the internal state so we can accept other operations. */
m_flags.state = NRF_FSTORAGE_STATE_IDLE;
m_flags.queue_running = false;
/* Free the current queue element. */
queue_free();
} break;
}
}
/* Start processing the queue if it is not running and fstorage is not paused. */
static void queue_start(void)
{
if ( (!nrf_atomic_flag_set_fetch(&m_flags.queue_running))
&& (!m_flags.paused))
{
queue_process();
}
}
/* Flash operation success callback. Keeps track of the progress of an operation. */
static bool on_operation_success(nrf_fstorage_sd_op_t * const p_op)
{
/* Reset the retry counter on success. */
m_flags.retries = 0;
switch (p_op->op_code)
{
case NRF_FSTORAGE_OP_WRITE:
{
/* Update the offset only if the operation is successful
* so that it can be retried in case it times out. */
uint32_t const chunk_len = MIN(p_op->write.len - p_op->write.offset,
NRF_FSTORAGE_SD_MAX_WRITE_SIZE);
p_op->write.offset += chunk_len;
if (p_op->write.offset == p_op->write.len)
{
return true;
}
} break;
case NRF_FSTORAGE_OP_ERASE:
{
p_op->erase.progress++;
if (p_op->erase.progress == p_op->erase.pages_to_erase)
{
return true;
}
} break;
default:
/* Should not happen. */
break;
}
return false;
}
/* Flash operation failure callback. */
static bool on_operation_failure(nrf_fstorage_sd_op_t const * p_op)
{
UNUSED_PARAMETER(p_op);
m_flags.retries++;
if (m_flags.retries > NRF_FSTORAGE_SD_MAX_RETRIES)
{
/* Maximum amount of retries reached. Give up. */
m_flags.retries = 0;
return true;
}
return false;
}
static ret_code_t init(nrf_fstorage_t * p_fs, void * p_param)
{
UNUSED_PARAMETER(p_param);
p_fs->p_flash_info = &m_flash_info;
if (!nrf_atomic_flag_set_fetch(&m_flags.initialized))
{
#if NRF_SDH_ENABLED
m_flags.sd_enabled = nrf_sdh_is_enabled();
#endif
(void) NRF_ATFIFO_INIT(m_fifo);
}
return NRF_SUCCESS;
}
static ret_code_t uninit(nrf_fstorage_t * p_fs, void * p_param)
{
UNUSED_PARAMETER(p_fs);
UNUSED_PARAMETER(p_param);
/* The state is re-initialized upon init().
* The common uninitialization code is run by the caller. */
memset(&m_flags, 0x00, sizeof(m_flags));
(void) nrf_atfifo_clear(m_fifo);
return NRF_SUCCESS;
}
static ret_code_t write(nrf_fstorage_t const * p_fs,
uint32_t dest,
void const * p_src,
uint32_t len,
void * p_param)
{
nrf_fstorage_sd_op_t * p_op;
nrf_atfifo_item_put_t iput_ctx;
/* Get a free queue element. */
p_op = nrf_atfifo_item_alloc(m_fifo, &iput_ctx);
if (p_op == NULL)
{
return NRF_ERROR_NO_MEM;
}
/* Initialize the operation. */
memset(p_op, 0x00, sizeof(nrf_fstorage_sd_op_t));
p_op->op_code = NRF_FSTORAGE_OP_WRITE;
p_op->p_fs = p_fs;
p_op->p_param = p_param;
p_op->write.dest = dest;
p_op->write.p_src = p_src;
p_op->write.len = len;
/* Put the operation on the queue. */
(void) nrf_atfifo_item_put(m_fifo, &iput_ctx);
queue_start();
return NRF_SUCCESS;
}
static ret_code_t read(nrf_fstorage_t const * p_fs, uint32_t src, void * p_dest, uint32_t len)
{
memcpy(p_dest, (uint32_t*)src, len);
return NRF_SUCCESS;
}
static ret_code_t erase(nrf_fstorage_t const * p_fs,
uint32_t page_addr,
uint32_t len,
void * p_param)
{
nrf_fstorage_sd_op_t * p_op;
nrf_atfifo_item_put_t iput_ctx;
/* Get a free queue element. */
p_op = nrf_atfifo_item_alloc(m_fifo, &iput_ctx);
if (p_op == NULL)
{
return NRF_ERROR_NO_MEM;
}
/* Initialize the operation. */
memset(p_op, 0x00, sizeof(nrf_fstorage_sd_op_t));
p_op->op_code = NRF_FSTORAGE_OP_ERASE;
p_op->p_fs = p_fs;
p_op->p_param = p_param;
p_op->erase.page = (page_addr / m_flash_info.erase_unit);
p_op->erase.pages_to_erase = len;
/* Put the operation on the queue. */
(void) nrf_atfifo_item_put(m_fifo, &iput_ctx);
queue_start();
return NRF_SUCCESS;
}
static uint8_t const * rmap(nrf_fstorage_t const * p_fs, uint32_t addr)
{
UNUSED_PARAMETER(p_fs);
return (uint8_t*)addr;
}
static uint8_t * wmap(nrf_fstorage_t const * p_fs, uint32_t addr)
{
UNUSED_PARAMETER(p_fs);
UNUSED_PARAMETER(addr);
/* Not supported. */
return NULL;
}
static bool is_busy(nrf_fstorage_t const * p_fs)
{
UNUSED_PARAMETER(p_fs);
return (m_flags.state != NRF_FSTORAGE_STATE_IDLE);
}
void nrf_fstorage_sys_evt_handler(uint32_t sys_evt, void * p_context)
{
UNUSED_PARAMETER(p_context);
if ( (sys_evt != NRF_EVT_FLASH_OPERATION_SUCCESS)
&& (sys_evt != NRF_EVT_FLASH_OPERATION_ERROR))
{
/* Ignore any non-flash events. */
return;
}
switch (m_flags.state)
{
case NRF_FSTORAGE_STATE_IDLE:
/* Ignore flash events if no flash operation was requested. */
return;
case NRF_FSTORAGE_STATE_OP_PENDING:
/* The SoftDevice has completed a flash operation that was not requested by fstorage.
* It should be possible to request an operation now.
* Process the queue at the end of this function. */
break;
case NRF_FSTORAGE_STATE_OP_EXECUTING:
{
/* Handle the result of a flash operation initiated by this module. */
bool operation_finished = false;
switch (sys_evt)
{
case NRF_EVT_FLASH_OPERATION_SUCCESS:
operation_finished = on_operation_success(m_p_cur_op);
break;
case NRF_EVT_FLASH_OPERATION_ERROR:
operation_finished = on_operation_failure(m_p_cur_op);
break;
default:
break;
}
if (operation_finished)
{
/* The operation has finished. Change state to NRF_FSTORAGE_STATE_IDLE
* so that queue_process() will fetch a new operation from the queue. */
m_flags.state = NRF_FSTORAGE_STATE_IDLE;
event_send(m_p_cur_op, (sys_evt == NRF_EVT_FLASH_OPERATION_SUCCESS) ?
NRF_SUCCESS : NRF_ERROR_TIMEOUT);
/* Free the queue element after sending out the event to prevent API calls made
* in the event context to queue elements indefinitely, without this function
* ever returning in case the SoftDevice calls are synchronous. */
queue_free();
}
} break;
}
if (!m_flags.paused)
{
queue_process();
}
else
{
/* A flash operation has completed. Let the SoftDevice change state. */
(void) nrf_sdh_request_continue();
}
}
bool nrf_fstorage_sdh_req_handler(nrf_sdh_req_evt_t req, void * p_context)
{
UNUSED_PARAMETER(req);
UNUSED_PARAMETER(p_context);
m_flags.paused = true;
/* If there are any operations ongoing, pause the SoftDevice state change. */
return (m_flags.state == NRF_FSTORAGE_STATE_IDLE);
}
void nrf_fstorage_sdh_state_handler(nrf_sdh_state_evt_t state, void * p_context)
{
UNUSED_PARAMETER(p_context);
if ( (state == NRF_SDH_EVT_STATE_ENABLED)
|| (state == NRF_SDH_EVT_STATE_DISABLED))
{
m_flags.paused = false;
m_flags.sd_enabled = (state == NRF_SDH_EVT_STATE_ENABLED);
/* Execute any operations still in the queue. */
queue_process();
}
}
/* Exported API implementation. */
nrf_fstorage_api_t nrf_fstorage_sd =
{
.init = init,
.uninit = uninit,
.read = read,
.write = write,
.erase = erase,
.rmap = rmap,
.wmap = wmap,
.is_busy = is_busy
};
#endif // NRF_FSTORAGE_ENABLED

View File

@ -0,0 +1,75 @@
/**
* 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_fstorage_sd SoftDevice implementation
* @ingroup nrf_fstorage
* @{
*
* @brief API implementation of fstorage that uses the SoftDevice.
*/
#ifndef NRF_FSTORAGE_SD_H__
#define NRF_FSTORAGE_SD_H__
#include "nrf_fstorage.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@brief API implementation that uses the SoftDevice.
*
* @details An fstorage instance with this API implementation can be initialized by providing
* this structure as a parameter to @ref nrf_fstorage_init.
* The structure is defined in @c nrf_fstorage_sd.c.
*/
extern nrf_fstorage_api_t nrf_fstorage_sd;
#ifdef __cplusplus
}
#endif
#endif // NRF_FSTORAGE_SD_H__
/** @} */

View File

@ -0,0 +1,348 @@
/**
* 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_SPI_MNGR)
#include "nrf_spi_mngr.h"
#include "nrf_assert.h"
#include "app_util_platform.h"
typedef volatile struct
{
bool transaction_in_progress;
uint8_t transaction_result;
} nrf_spi_mngr_cb_data_t;
static ret_code_t start_transfer(nrf_spi_mngr_t const * p_nrf_spi_mngr)
{
ASSERT(p_nrf_spi_mngr != NULL);
// use a local variable to avoid using two volatile variables in one
// expression
uint8_t curr_transfer_idx = p_nrf_spi_mngr->p_nrf_spi_mngr_cb->current_transfer_idx;
nrf_spi_mngr_transfer_t const * p_transfer =
&p_nrf_spi_mngr->p_nrf_spi_mngr_cb->p_current_transaction->p_transfers[curr_transfer_idx];
return nrf_drv_spi_transfer(&p_nrf_spi_mngr->spi,
p_transfer->p_tx_data, p_transfer->tx_length,
p_transfer->p_rx_data, p_transfer->rx_length);
}
static void transaction_begin_signal(nrf_spi_mngr_t const * p_nrf_spi_mngr)
{
ASSERT(p_nrf_spi_mngr != NULL);
nrf_spi_mngr_transaction_t const * p_current_transaction =
p_nrf_spi_mngr->p_nrf_spi_mngr_cb->p_current_transaction;
if (p_current_transaction->begin_callback != NULL)
{
void * p_user_data = p_current_transaction->p_user_data;
p_current_transaction->begin_callback(p_user_data);
}
}
static void transaction_end_signal(nrf_spi_mngr_t const * p_nrf_spi_mngr,
ret_code_t result)
{
ASSERT(p_nrf_spi_mngr != NULL);
nrf_spi_mngr_transaction_t const * p_current_transaction =
p_nrf_spi_mngr->p_nrf_spi_mngr_cb->p_current_transaction;
if (p_current_transaction->end_callback != NULL)
{
void * p_user_data = p_current_transaction->p_user_data;
p_current_transaction->end_callback(result, p_user_data);
}
}
static void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
void * p_context);
// This function starts pending transaction if there is no current one or
// when 'switch_transaction' parameter is set to true. It is important to
// switch to new transaction without setting 'p_nrf_spi_mngr->p_curr_transaction'
// to NULL in between, since this pointer is used to check idle status - see
// 'nrf_spi_mngr_is_idle()'.
static void start_pending_transaction(nrf_spi_mngr_t const * p_nrf_spi_mngr,
bool switch_transaction)
{
ASSERT(p_nrf_spi_mngr != NULL);
while (1)
{
bool start_transaction = false;
nrf_spi_mngr_cb_t * p_cb = p_nrf_spi_mngr->p_nrf_spi_mngr_cb;
CRITICAL_REGION_ENTER();
if (switch_transaction || nrf_spi_mngr_is_idle(p_nrf_spi_mngr))
{
if (nrf_queue_pop(p_nrf_spi_mngr->p_queue,
(void *)(&p_cb->p_current_transaction))
== NRF_SUCCESS)
{
start_transaction = true;
}
else
{
p_cb->p_current_transaction = NULL;
}
}
CRITICAL_REGION_EXIT();
if (!start_transaction)
{
return;
}
nrf_drv_spi_config_t const * p_instance_cfg;
if (p_cb->p_current_transaction->p_required_spi_cfg == NULL)
{
p_instance_cfg = &p_cb->default_configuration;
}
else
{
p_instance_cfg = p_cb->p_current_transaction->p_required_spi_cfg;
}
ret_code_t result;
if (memcmp(p_cb->p_current_configuration, p_instance_cfg, sizeof(*p_instance_cfg)) != 0)
{
nrf_drv_spi_uninit(&p_nrf_spi_mngr->spi);
result = nrf_drv_spi_init(&p_nrf_spi_mngr->spi,
p_instance_cfg,
spi_event_handler,
(void *)p_nrf_spi_mngr);
ASSERT(result == NRF_SUCCESS);
p_cb->p_current_configuration = p_instance_cfg;
}
// Try to start first transfer for this new transaction.
p_cb->current_transfer_idx = 0;
// Execute user code if available before starting transaction
transaction_begin_signal(p_nrf_spi_mngr);
result = start_transfer(p_nrf_spi_mngr);
// If transaction started successfully there is nothing more to do here now.
if (result == NRF_SUCCESS)
{
return;
}
// Transfer failed to start - notify user that this transaction
// cannot be started and try with next one (in next iteration of
// the loop).
transaction_end_signal(p_nrf_spi_mngr, result);
switch_transaction = true;
}
}
// This function shall be called to handle SPI events. It shall be mainly used by SPI IRQ for
// finished tranfer.
static void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
void * p_context)
{
ASSERT(p_event != NULL);
ASSERT(p_context != NULL);
ret_code_t result;
nrf_spi_mngr_cb_t * p_cb = ((nrf_spi_mngr_t const *)p_context)->p_nrf_spi_mngr_cb;
// This callback should be called only during transaction.
ASSERT(p_cb->p_current_transaction != NULL);
if (p_event->type == NRF_DRV_SPI_EVENT_DONE)
{
result = NRF_SUCCESS;
// Transfer finished successfully. If there is another one to be
// performed in the current transaction, start it now.
// use a local variable to avoid using two volatile variables in one
// expression
uint8_t curr_transfer_idx = p_cb->current_transfer_idx;
++curr_transfer_idx;
if (curr_transfer_idx < p_cb->p_current_transaction->number_of_transfers)
{
p_cb->current_transfer_idx = curr_transfer_idx;
result = start_transfer(((nrf_spi_mngr_t const *)p_context));
if (result == NRF_SUCCESS)
{
// The current transaction is running and its next transfer
// has been successfully started. There is nothing more to do.
return;
}
// if the next transfer could not be started due to some error
// we finish the transaction with this error code as the result
}
}
else
{
result = NRF_ERROR_INTERNAL;
}
// The current transaction has been completed or interrupted by some error.
// Notify the user and start next one (if there is any).
transaction_end_signal(((nrf_spi_mngr_t const *)p_context), result);
// we switch transactions here ('p_nrf_spi_mngr->p_current_transaction' is set
// to NULL only if there is nothing more to do) in order to not generate
// spurious idle status (even for a moment)
start_pending_transaction(((nrf_spi_mngr_t const *)p_context), true);
}
ret_code_t nrf_spi_mngr_init(nrf_spi_mngr_t const * p_nrf_spi_mngr,
nrf_drv_spi_config_t const * p_default_spi_config)
{
ASSERT(p_nrf_spi_mngr != NULL);
ASSERT(p_nrf_spi_mngr->p_queue != NULL);
ASSERT(p_nrf_spi_mngr->p_queue->size > 0);
ASSERT(p_default_spi_config != NULL);
ret_code_t err_code;
err_code = nrf_drv_spi_init(&p_nrf_spi_mngr->spi,
p_default_spi_config,
spi_event_handler,
(void *)p_nrf_spi_mngr);
if (err_code == NRF_SUCCESS)
{
nrf_spi_mngr_cb_t * p_cb = p_nrf_spi_mngr->p_nrf_spi_mngr_cb;
p_cb->p_current_transaction = NULL;
p_cb->default_configuration = *p_default_spi_config;
p_cb->p_current_configuration = &p_cb->default_configuration;
}
return err_code;
}
void nrf_spi_mngr_uninit(nrf_spi_mngr_t const * p_nrf_spi_mngr)
{
ASSERT(p_nrf_spi_mngr != NULL);
nrf_drv_spi_uninit(&p_nrf_spi_mngr->spi);
p_nrf_spi_mngr->p_nrf_spi_mngr_cb->p_current_transaction = NULL;
}
ret_code_t nrf_spi_mngr_schedule(nrf_spi_mngr_t const * p_nrf_spi_mngr,
nrf_spi_mngr_transaction_t const * p_transaction)
{
ASSERT(p_nrf_spi_mngr != NULL);
ASSERT(p_transaction != NULL);
ASSERT(p_transaction->p_transfers != NULL);
ASSERT(p_transaction->number_of_transfers != 0);
ret_code_t result = nrf_queue_push(p_nrf_spi_mngr->p_queue, (void *)(&p_transaction));
if (result == NRF_SUCCESS)
{
// New transaction has been successfully added to queue,
// so if we are currently idle it's time to start the job.
start_pending_transaction(p_nrf_spi_mngr, false);
}
return result;
}
static void spi_internal_transaction_cb(ret_code_t result, void * p_user_data)
{
nrf_spi_mngr_cb_data_t * p_cb_data = (nrf_spi_mngr_cb_data_t *)p_user_data;
p_cb_data->transaction_result = result;
p_cb_data->transaction_in_progress = false;
}
ret_code_t nrf_spi_mngr_perform(nrf_spi_mngr_t const * p_nrf_spi_mngr,
nrf_drv_spi_config_t const * p_config,
nrf_spi_mngr_transfer_t const * p_transfers,
uint8_t number_of_transfers,
void (* user_function)(void))
{
ASSERT(p_nrf_spi_mngr != NULL);
ASSERT(p_transfers != NULL);
ASSERT(number_of_transfers != 0);
nrf_spi_mngr_cb_data_t cb_data =
{
.transaction_in_progress = true
};
nrf_spi_mngr_transaction_t internal_transaction =
{
.begin_callback = NULL,
.end_callback = spi_internal_transaction_cb,
.p_user_data = (void *)&cb_data,
.p_transfers = p_transfers,
.number_of_transfers = number_of_transfers,
.p_required_spi_cfg = p_config
};
ret_code_t result = nrf_spi_mngr_schedule(p_nrf_spi_mngr, &internal_transaction);
VERIFY_SUCCESS(result);
while (cb_data.transaction_in_progress)
{
if (user_function)
{
user_function();
}
}
return cb_data.transaction_result;
}
#endif //NRF_MODULE_ENABLED(NRF_SPI_MNGR)

View File

@ -0,0 +1,310 @@
/**
* 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.
*
*/
#ifndef NRF_SPI_MNGR_H__
#define NRF_SPI_MNGR_H__
#include <stdint.h>
#include "nrf_drv_spi.h"
#include "sdk_errors.h"
#include "nrf_queue.h"
#ifdef __cplusplus
extern "C" {
#endif
/*lint -save -e491*/
#ifndef NRF_SPI_MNGR_BUFFERS_IN_RAM
#define NRF_SPI_MNGR_BUFFERS_IN_RAM defined(SPIM_PRESENT)
#endif
#if NRF_SPI_MNGR_BUFFERS_IN_RAM
#define NRF_SPI_MNGR_BUFFER_LOC_IND
#else
#define NRF_SPI_MNGR_BUFFER_LOC_IND const
#endif
/*lint -restore*/
/**
* @defgroup nrf_spi_mngr SPI transaction manager
* @{
* @ingroup app_common
*
* @brief Module for scheduling SPI transactions.
*/
/**
* @brief Macro for creating a simple SPI transfer.
*
* @param[in] _p_tx_data Pointer to the data to be sent.
* @param[in] _tx_length Number of bytes to send.
* @param[in] _p_rx_data Pointer to a buffer for received data.
* @param[in] _rx_length Number of bytes to receive.
*/
#define NRF_SPI_MNGR_TRANSFER(_p_tx_data, _tx_length, _p_rx_data, _rx_length) \
{ \
.p_tx_data = (uint8_t const *)_p_tx_data, \
.tx_length = (uint8_t) _tx_length, \
.p_rx_data = (uint8_t *) _p_rx_data, \
.rx_length = (uint8_t) _rx_length, \
}
/**
* @brief SPI transaction end callback prototype.
*
* @param result Result of operation (NRF_SUCCESS on success,
* otherwise a relevant error code).
* @param[in] p_user_data Pointer to user data defined in transaction
* descriptor.
*/
typedef void (* nrf_spi_mngr_callback_end_t)(ret_code_t result, void * p_user_data);
/**
* @brief SPI transaction begin callback prototype.
*
* @param[in] p_user_data Pointer to user data defined in transaction
* descriptor.
*/
typedef void (* nrf_spi_mngr_callback_begin_t)(void * p_user_data);
/**
* @brief SPI transfer descriptor.
*/
typedef struct
{
uint8_t const * p_tx_data; ///< Pointer to the data to be sent.
uint8_t tx_length; ///< Number of bytes to send.
uint8_t * p_rx_data; ///< Pointer to a buffer for received data.
uint8_t rx_length; ///< Number of bytes to receive.
} nrf_spi_mngr_transfer_t;
/**
* @brief SPI transaction descriptor.
*/
typedef struct
{
nrf_spi_mngr_callback_begin_t begin_callback;
///< User-specified function to be called before the transaction is started.
nrf_spi_mngr_callback_end_t end_callback;
///< User-specified function to be called after the transaction is finished.
void * p_user_data;
///< Pointer to user data to be passed to the end_callback.
nrf_spi_mngr_transfer_t const * p_transfers;
///< Pointer to the array of transfers that make up the transaction.
uint8_t number_of_transfers;
///< Number of transfers that make up the transaction.
nrf_drv_spi_config_t const * p_required_spi_cfg;
///< Pointer to instance hardware configuration.
} nrf_spi_mngr_transaction_t;
/**
* @brief SPI instance control block.
*/
typedef struct
{
nrf_spi_mngr_transaction_t const * volatile p_current_transaction;
///< Currently realized transaction.
nrf_drv_spi_config_t default_configuration;
///< Default hardware configuration.
nrf_drv_spi_config_t const * p_current_configuration;
///< Pointer to current hardware configuration.
uint8_t volatile current_transfer_idx;
///< Index of currently performed transfer (within current transaction).
} nrf_spi_mngr_cb_t;
/**
* @brief SPI transaction manager instance.
*/
typedef struct
{
nrf_spi_mngr_cb_t * p_nrf_spi_mngr_cb;
///< Control block of instance.
nrf_queue_t const * p_queue;
///< Transaction queue.
nrf_drv_spi_t spi;
///< Pointer to SPI master driver instance.
} nrf_spi_mngr_t;
/**
* @brief Macro for simplifying the defining of an SPI transaction manager
* instance.
*
* This macro allocates a static buffer for the transaction queue.
* Therefore, it should be used in only one place in the code for a given
* instance.
*
* @note The queue size is the maximum number of pending transactions
* not counting the one that is currently realized. This means that
* for an empty queue with size of for example 4 elements, it is
* possible to schedule up to 5 transactions.
*
* @param[in] _nrf_spi_mngr_name Name of instance to be created.
* @param[in] _queue_size Size of the transaction queue (maximum number
* of pending transactions).
* @param[in] _spi_idx Index of hardware SPI instance to be used.
*/
#define NRF_SPI_MNGR_DEF(_nrf_spi_mngr_name, _queue_size, _spi_idx) \
NRF_QUEUE_DEF(nrf_spi_mngr_transaction_t const *, \
_nrf_spi_mngr_name##_queue, \
(_queue_size), \
NRF_QUEUE_MODE_NO_OVERFLOW); \
static nrf_spi_mngr_cb_t CONCAT_2(_nrf_spi_mngr_name, _cb); \
static const nrf_spi_mngr_t _nrf_spi_mngr_name = \
{ \
.p_nrf_spi_mngr_cb = &CONCAT_2(_nrf_spi_mngr_name, _cb), \
.p_queue = &_nrf_spi_mngr_name##_queue, \
.spi = NRF_DRV_SPI_INSTANCE(_spi_idx) \
}
/**
* @brief Function for initializing an SPI transaction manager instance.
*
* @param[in] p_nrf_spi_mngr Pointer to the instance to be initialized.
* @param[in] p_default_spi_config Pointer to the SPI driver configuration. This configuration
* will be used whenever the scheduled transaction will have
* p_spi_config set to NULL value.
*
* @return Values returned by the @ref nrf_drv_spi_init function.
*/
ret_code_t nrf_spi_mngr_init(nrf_spi_mngr_t const * p_nrf_spi_mngr,
nrf_drv_spi_config_t const * p_default_spi_config);
/**
* @brief Function for uninitializing an SPI transaction manager instance.
*
* @param[in] p_nrf_spi_mngr Pointer to the instance to be uninitialized.
*/
void nrf_spi_mngr_uninit(nrf_spi_mngr_t const * p_nrf_spi_mngr);
/**
* @brief Function for scheduling an SPI transaction.
*
* The transaction is enqueued and started as soon as the SPI bus is
* available, thus when all previously scheduled transactions have been
* finished (possibly immediately).
*
* @note If @ref nrf_spi_mngr_transaction_t::p_required_spi_cfg
* is set to a non-NULL value the module will compare it with
* @ref nrf_spi_mngr_cb_t::p_current_configuration and reinitialize hardware
* SPI instance with new parameters if any differences are found.
* If @ref nrf_spi_mngr_transaction_t::p_required_spi_cfg is set to NULL then
* it will treat it as it would be set to @ref nrf_spi_mngr_cb_t::default_configuration.
*
* @param[in] p_nrf_spi_mngr Pointer to the SPI transaction manager instance.
* @param[in] p_transaction Pointer to the descriptor of the transaction to be
* scheduled.
*
* @retval NRF_SUCCESS If the transaction has been successfully scheduled.
* @retval NRF_ERROR_NO_MEM If the queue is full (Only if queue in
* @ref NRF_QUEUE_MODE_NO_OVERFLOW).
*/
ret_code_t nrf_spi_mngr_schedule(nrf_spi_mngr_t const * p_nrf_spi_mngr,
nrf_spi_mngr_transaction_t const * p_transaction);
/**
* @brief Function for scheduling a transaction and waiting until it is finished.
*
* This function schedules a transaction that consists of one or more transfers
* and waits until it is finished.
*
* @param[in] p_nrf_spi_mngr Pointer to the SPI transaction manager instance.
* @param[in] p_config Required SPI configuration.
* @param[in] p_transfers Pointer to an array of transfers to be performed.
* @param number_of_transfers Number of transfers to be performed.
* @param user_function User-specified function to be called while
* waiting. NULL if such functionality
* is not needed.
*
* @retval NRF_SUCCESS If the transfers have been successfully realized.
* @retval NRF_ERROR_BUSY If some transfers are already being performed.
* @retval - Other error codes mean that the transaction has failed
* with the error reported by @ref nrf_drv_spi_transfer().
*/
ret_code_t nrf_spi_mngr_perform(nrf_spi_mngr_t const * p_nrf_spi_mngr,
nrf_drv_spi_config_t const * p_config,
nrf_spi_mngr_transfer_t const * p_transfers,
uint8_t number_of_transfers,
void (* user_function)(void));
/**
* @brief Function for getting the current state of an SPI transaction manager
* instance.
*
* @param[in] p_nrf_spi_mngr Pointer to the SPI transaction manager instance.
*
* @retval true If all scheduled transactions have been finished.
* @retval false Otherwise.
*/
__STATIC_INLINE bool nrf_spi_mngr_is_idle(nrf_spi_mngr_t const * p_nrf_spi_mngr)
{
return (p_nrf_spi_mngr->p_nrf_spi_mngr_cb->p_current_transaction == NULL);
}
/**
*@}
**/
//typedef int p_current_transaction;
#ifdef __cplusplus
}
#endif
#endif // NRF_SPI_MNGR_H__

View File

@ -0,0 +1,164 @@
/**
* Copyright (c) 2011 - 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_STRERROR)
#include "nrf_strerror.h"
#include "sdk_errors.h"
// #define NRF_ERROR_MODULE_NOT_INITIALZED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0000)
/**
* @brief Macro for adding an entity to the description array.
*
* Macro that helps to create a single entity in the description array.
*/
#define NRF_STRERROR_ENTITY(mnemonic) {.code = mnemonic, .name = #mnemonic}
/**
* @brief Array entity element that describes an error.
*/
typedef struct
{
ret_code_t code; /**< Error code. */
char const * name; /**< Descriptive name (the same as the internal error mnemonic). */
}nrf_strerror_desc_t;
/**
* @brief Unknown error code.
*
* The constant string used by @ref nrf_strerror_get when the error description was not found.
*/
static char const m_unknown_str[] = "Unknown error code";
/**
* @brief Array with error codes.
*
* Array that describes error codes.
*
* @note It is required for this array to have error codes placed in ascending order.
* This condition is checked in automatic unit test before the release.
*/
static nrf_strerror_desc_t const nrf_strerror_array[] =
{
NRF_STRERROR_ENTITY(NRF_SUCCESS),
NRF_STRERROR_ENTITY(NRF_ERROR_SVC_HANDLER_MISSING),
NRF_STRERROR_ENTITY(NRF_ERROR_SOFTDEVICE_NOT_ENABLED),
NRF_STRERROR_ENTITY(NRF_ERROR_INTERNAL),
NRF_STRERROR_ENTITY(NRF_ERROR_NO_MEM),
NRF_STRERROR_ENTITY(NRF_ERROR_NOT_FOUND),
NRF_STRERROR_ENTITY(NRF_ERROR_NOT_SUPPORTED),
NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_PARAM),
NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_STATE),
NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_LENGTH),
NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_FLAGS),
NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_DATA),
NRF_STRERROR_ENTITY(NRF_ERROR_DATA_SIZE),
NRF_STRERROR_ENTITY(NRF_ERROR_TIMEOUT),
NRF_STRERROR_ENTITY(NRF_ERROR_NULL),
NRF_STRERROR_ENTITY(NRF_ERROR_FORBIDDEN),
NRF_STRERROR_ENTITY(NRF_ERROR_INVALID_ADDR),
NRF_STRERROR_ENTITY(NRF_ERROR_BUSY),
#ifdef NRF_ERROR_CONN_COUNT
NRF_STRERROR_ENTITY(NRF_ERROR_CONN_COUNT),
#endif
#ifdef NRF_ERROR_RESOURCES
NRF_STRERROR_ENTITY(NRF_ERROR_RESOURCES),
#endif
/* SDK Common errors */
NRF_STRERROR_ENTITY(NRF_ERROR_MODULE_NOT_INITIALIZED),
NRF_STRERROR_ENTITY(NRF_ERROR_MUTEX_INIT_FAILED),
NRF_STRERROR_ENTITY(NRF_ERROR_MUTEX_LOCK_FAILED),
NRF_STRERROR_ENTITY(NRF_ERROR_MUTEX_UNLOCK_FAILED),
NRF_STRERROR_ENTITY(NRF_ERROR_MUTEX_COND_INIT_FAILED),
NRF_STRERROR_ENTITY(NRF_ERROR_MODULE_ALREADY_INITIALIZED),
NRF_STRERROR_ENTITY(NRF_ERROR_STORAGE_FULL),
NRF_STRERROR_ENTITY(NRF_ERROR_API_NOT_IMPLEMENTED),
NRF_STRERROR_ENTITY(NRF_ERROR_FEATURE_NOT_ENABLED),
NRF_STRERROR_ENTITY(NRF_ERROR_IO_PENDING),
/* TWI error codes */
NRF_STRERROR_ENTITY(NRF_ERROR_DRV_TWI_ERR_OVERRUN),
NRF_STRERROR_ENTITY(NRF_ERROR_DRV_TWI_ERR_ANACK),
NRF_STRERROR_ENTITY(NRF_ERROR_DRV_TWI_ERR_DNACK),
/* IPSP error codes */
NRF_STRERROR_ENTITY(NRF_ERROR_BLE_IPSP_RX_PKT_TRUNCATED),
NRF_STRERROR_ENTITY(NRF_ERROR_BLE_IPSP_CHANNEL_ALREADY_EXISTS),
NRF_STRERROR_ENTITY(NRF_ERROR_BLE_IPSP_LINK_DISCONNECTED),
NRF_STRERROR_ENTITY(NRF_ERROR_BLE_IPSP_PEER_REJECTED)
};
char const * nrf_strerror_get(ret_code_t code)
{
char const * p_ret = nrf_strerror_find(code);
return (p_ret == NULL) ? m_unknown_str : p_ret;
}
char const * nrf_strerror_find(ret_code_t code)
{
nrf_strerror_desc_t const * p_start;
nrf_strerror_desc_t const * p_end;
p_start = nrf_strerror_array;
p_end = nrf_strerror_array + ARRAY_SIZE(nrf_strerror_array);
while (p_start < p_end)
{
nrf_strerror_desc_t const * p_mid = p_start + ((p_end - p_start) / 2);
ret_code_t mid_c = p_mid->code;
if (mid_c > code)
{
p_end = p_mid;
}
else if (mid_c < code)
{
p_start = p_mid + 1;
}
else
{
return p_mid->name;
}
}
return NULL;
}
#endif /* NRF_STRERROR enabled */

View File

@ -0,0 +1,89 @@
/**
* 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.
*
*/
/**
* @defgroup nrf_strerror Error code to string converter
* @ingroup app_common
*
* @brief Module for converting error code into a printable string.
* @{
*/
#ifndef NRF_STRERROR_H__
#define NRF_STRERROR_H__
#include "sdk_errors.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Function for getting a printable error string.
*
* @param code Error code to convert.
*
* @note This function cannot fail.
* For the function that may fail with error translation, see @ref nrf_strerror_find.
*
* @return Pointer to the printable string.
* If the string is not found,
* it returns a simple string that says that the error is unknown.
*/
char const * nrf_strerror_get(ret_code_t code);
/**
* @brief Function for finding a printable error string.
*
* This function gets the error string in the same way as @ref nrf_strerror_get,
* but if the string is not found, it returns NULL.
*
* @param code Error code to convert.
* @return Pointer to the printable string.
* If the string is not found, NULL is returned.
*/
char const * nrf_strerror_find(ret_code_t code);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* NRF_STRERROR_H__ */

View File

@ -0,0 +1,366 @@
/**
* 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.
*
*/
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_TWI_MNGR)
#include "nrf_twi_mngr.h"
#include "nrf_assert.h"
#include "app_util_platform.h"
typedef volatile struct
{
bool transaction_in_progress;
uint8_t transaction_result;
} nrf_twi_mngr_cb_data_t;
static ret_code_t start_transfer(nrf_twi_mngr_t const * p_nrf_twi_mngr)
{
ASSERT(p_nrf_twi_mngr != NULL);
// Pointer for cleaner code.
nrf_twi_mngr_cb_t * p_cb = p_nrf_twi_mngr->p_nrf_twi_mngr_cb;
// [use a local variable to avoid using two volatile variables in one
// expression]
uint8_t current_transfer_idx = p_cb->current_transfer_idx;
nrf_twi_mngr_transfer_t const * p_transfer =
&p_cb->p_current_transaction->p_transfers[current_transfer_idx];
uint8_t address = NRF_TWI_MNGR_OP_ADDRESS(p_transfer->operation);
nrf_drv_twi_xfer_desc_t xfer_desc;
uint32_t flags;
xfer_desc.address = address;
xfer_desc.p_primary_buf = p_transfer->p_data;
xfer_desc.primary_length = p_transfer->length;
/* If it is possible try to bind two transfers together. They can be combined if:
* - there is no stop condition after current transfer.
* - current transfer is TX.
* - there is at least one more transfer in the transaction.
* - address of next transfer is the same as current transfer.
*/
if ((p_transfer->flags & NRF_TWI_MNGR_NO_STOP) &&
!NRF_TWI_MNGR_IS_READ_OP(p_transfer->operation) &&
// Adding 1 to check if next transfer is from the same transaction.
((current_transfer_idx + 1) < p_cb->p_current_transaction->number_of_transfers) &&
(NRF_TWI_MNGR_OP_ADDRESS(p_transfer->operation) ==
NRF_TWI_MNGR_OP_ADDRESS(p_cb->p_current_transaction->
p_transfers[current_transfer_idx + 1].operation)))
{
nrf_twi_mngr_transfer_t const * p_second_transfer =
&p_cb->p_current_transaction->p_transfers[current_transfer_idx + 1];
xfer_desc.p_secondary_buf = p_second_transfer->p_data;
xfer_desc.secondary_length = p_second_transfer->length;
xfer_desc.type = NRF_TWI_MNGR_IS_READ_OP(p_second_transfer->operation) ?
NRF_DRV_TWI_XFER_TXRX : NRF_DRV_TWI_XFER_TXTX;
flags = (p_second_transfer->flags & NRF_TWI_MNGR_NO_STOP) ? NRF_DRV_TWI_FLAG_TX_NO_STOP : 0;
p_cb->current_transfer_idx++;
}
else
{
xfer_desc.type = NRF_TWI_MNGR_IS_READ_OP(p_transfer->operation) ? NRF_DRV_TWI_XFER_RX :
NRF_DRV_TWI_XFER_TX;
xfer_desc.p_secondary_buf = NULL;
xfer_desc.secondary_length = 0;
flags = (p_transfer->flags & NRF_TWI_MNGR_NO_STOP) ? NRF_DRV_TWI_FLAG_TX_NO_STOP : 0;
}
return nrf_drv_twi_xfer(&p_nrf_twi_mngr->twi, &xfer_desc, flags);
}
static void transaction_end_signal(nrf_twi_mngr_t const * p_nrf_twi_mngr,
ret_code_t result)
{
ASSERT(p_nrf_twi_mngr != NULL);
if (p_nrf_twi_mngr->p_nrf_twi_mngr_cb->p_current_transaction->callback)
{
// [use a local variable to avoid using two volatile variables in one
// expression]
void * p_user_data = p_nrf_twi_mngr->p_nrf_twi_mngr_cb->p_current_transaction->p_user_data;
p_nrf_twi_mngr->p_nrf_twi_mngr_cb->p_current_transaction->callback(result, p_user_data);
}
}
static void twi_event_handler(nrf_drv_twi_evt_t const * p_event,
void * p_context);
// This function starts pending transaction if there is no current one or
// when 'switch_transaction' parameter is set to true. It is important to
// switch to new transaction without setting 'p_nrf_twi_mngr->p_current_transaction'
// to NULL in between, since this pointer is used to check idle status - see
// 'nrf_twi_mngr_is_idle()'.
static void start_pending_transaction(nrf_twi_mngr_t const * p_nrf_twi_mngr,
bool switch_transaction)
{
ASSERT(p_nrf_twi_mngr != NULL);
// Pointer for cleaner code.
nrf_twi_mngr_cb_t * p_cb = p_nrf_twi_mngr->p_nrf_twi_mngr_cb;
for (;;)
{
bool start_transaction = false;
CRITICAL_REGION_ENTER();
if (switch_transaction || nrf_twi_mngr_is_idle(p_nrf_twi_mngr))
{
if (nrf_queue_pop(p_nrf_twi_mngr->p_queue, (void *)(&p_cb->p_current_transaction))
== NRF_SUCCESS)
{
start_transaction = true;
}
else
{
p_cb->p_current_transaction = NULL;
}
}
CRITICAL_REGION_EXIT();
if (!start_transaction)
{
return;
}
else
{
ret_code_t result;
nrf_drv_twi_config_t const * p_instance_cfg =
p_cb->p_current_transaction->p_required_twi_cfg == NULL ?
&p_cb->default_configuration :
p_cb->p_current_transaction->p_required_twi_cfg;
if (memcmp(p_cb->p_current_configuration, p_instance_cfg, sizeof(*p_instance_cfg)) != 0)
{
ret_code_t err_code;
nrf_drv_twi_uninit(&p_nrf_twi_mngr->twi);
err_code = nrf_drv_twi_init(&p_nrf_twi_mngr->twi,
p_instance_cfg,
twi_event_handler,
(void *)p_nrf_twi_mngr);
ASSERT(err_code == NRF_SUCCESS);
nrf_drv_twi_enable(&p_nrf_twi_mngr->twi);
UNUSED_VARIABLE(err_code);
p_cb->p_current_configuration = p_instance_cfg;
}
// Try to start first transfer for this new transaction.
p_cb->current_transfer_idx = 0;
result = start_transfer(p_nrf_twi_mngr);
// If transaction started successfully there is nothing more to do here now.
if (result == NRF_SUCCESS)
{
return;
}
// Transfer failed to start - notify user that this transaction
// cannot be started and try with next one (in next iteration of
// the loop).
transaction_end_signal(p_nrf_twi_mngr, result);
switch_transaction = true;
}
}
}
static void twi_event_handler(nrf_drv_twi_evt_t const * p_event,
void * p_context)
{
ASSERT(p_event != NULL);
nrf_twi_mngr_t * p_nrf_twi_mngr = (nrf_twi_mngr_t *)p_context;
ret_code_t result;
// This callback should be called only during transaction.
ASSERT(p_nrf_twi_mngr->p_nrf_twi_mngr_cb->p_current_transaction != NULL);
if (p_event->type == NRF_DRV_TWI_EVT_DONE)
{
result = NRF_SUCCESS;
// Transfer finished successfully. If there is another one to be
// performed in the current transaction, start it now.
// [use a local variable to avoid using two volatile variables in one
// expression]
uint8_t current_transfer_idx = p_nrf_twi_mngr->p_nrf_twi_mngr_cb->current_transfer_idx;
++current_transfer_idx;
if (current_transfer_idx <
p_nrf_twi_mngr->p_nrf_twi_mngr_cb->p_current_transaction->number_of_transfers)
{
p_nrf_twi_mngr->p_nrf_twi_mngr_cb->current_transfer_idx = current_transfer_idx;
result = start_transfer(p_nrf_twi_mngr);
if (result == NRF_SUCCESS)
{
// The current transaction goes on and we've successfully
// started its next transfer -> there is nothing more to do.
return;
}
// [if the next transfer could not be started due to some error
// we finish the transaction with this error code as the result]
}
}
else
{
result = NRF_ERROR_INTERNAL;
}
// The current transaction has been completed or interrupted by some error.
// Notify the user and start next one (if there is any).
transaction_end_signal(p_nrf_twi_mngr, result);
// [we switch transactions here ('p_nrf_twi_mngr->p_current_transaction' is set
// to NULL only if there is nothing more to do) in order to not generate
// spurious idle status (even for a moment)]
start_pending_transaction(p_nrf_twi_mngr, true);
}
ret_code_t nrf_twi_mngr_init(nrf_twi_mngr_t const * p_nrf_twi_mngr,
nrf_drv_twi_config_t const * p_default_twi_config)
{
ASSERT(p_nrf_twi_mngr != NULL);
ASSERT(p_nrf_twi_mngr->p_queue != NULL);
ASSERT(p_nrf_twi_mngr->p_queue->size > 0);
ASSERT(p_default_twi_config != NULL);
ret_code_t err_code;
err_code = nrf_drv_twi_init(&p_nrf_twi_mngr->twi,
p_default_twi_config,
twi_event_handler,
(void *)p_nrf_twi_mngr);
VERIFY_SUCCESS(err_code);
nrf_drv_twi_enable(&p_nrf_twi_mngr->twi);
p_nrf_twi_mngr->p_nrf_twi_mngr_cb->p_current_transaction = NULL;
p_nrf_twi_mngr->p_nrf_twi_mngr_cb->default_configuration = *p_default_twi_config;
p_nrf_twi_mngr->p_nrf_twi_mngr_cb->p_current_configuration =
&p_nrf_twi_mngr->p_nrf_twi_mngr_cb->default_configuration;
return NRF_SUCCESS;
}
void nrf_twi_mngr_uninit(nrf_twi_mngr_t const * p_nrf_twi_mngr)
{
ASSERT(p_nrf_twi_mngr != NULL);
nrf_drv_twi_uninit(&p_nrf_twi_mngr->twi);
p_nrf_twi_mngr->p_nrf_twi_mngr_cb->p_current_transaction = NULL;
}
ret_code_t nrf_twi_mngr_schedule(nrf_twi_mngr_t const * p_nrf_twi_mngr,
nrf_twi_mngr_transaction_t const * p_transaction)
{
ASSERT(p_nrf_twi_mngr != NULL);
ASSERT(p_transaction != NULL);
ASSERT(p_transaction->p_transfers != NULL);
ASSERT(p_transaction->number_of_transfers != 0);
ret_code_t result = NRF_SUCCESS;
result = nrf_queue_push(p_nrf_twi_mngr->p_queue, (void *)(&p_transaction));
if (result == NRF_SUCCESS)
{
// New transaction has been successfully added to queue,
// so if we are currently idle it's time to start the job.
start_pending_transaction(p_nrf_twi_mngr, false);
}
return result;
}
static void internal_transaction_cb(ret_code_t result, void * p_user_data)
{
nrf_twi_mngr_cb_data_t *p_cb_data = (nrf_twi_mngr_cb_data_t *)p_user_data;
p_cb_data->transaction_result = result;
p_cb_data->transaction_in_progress = false;
}
ret_code_t nrf_twi_mngr_perform(nrf_twi_mngr_t const * p_nrf_twi_mngr,
nrf_drv_twi_config_t const * p_config,
nrf_twi_mngr_transfer_t const * p_transfers,
uint8_t number_of_transfers,
void (* user_function)(void))
{
ASSERT(p_nrf_twi_mngr != NULL);
ASSERT(p_transfers != NULL);
ASSERT(number_of_transfers != 0);
nrf_twi_mngr_cb_data_t cb_data =
{
.transaction_in_progress = true
};
nrf_twi_mngr_transaction_t internal_transaction =
{
.callback = internal_transaction_cb,
.p_user_data = (void *)&cb_data,
.p_transfers = p_transfers,
.number_of_transfers = number_of_transfers,
.p_required_twi_cfg = p_config
};
ret_code_t result = nrf_twi_mngr_schedule(p_nrf_twi_mngr, &internal_transaction);
VERIFY_SUCCESS(result);
while (cb_data.transaction_in_progress)
{
if (user_function)
{
user_function();
}
}
return cb_data.transaction_result;
}
#endif //NRF_MODULE_ENABLED(NRF_TWI_MNGR)

View File

@ -0,0 +1,342 @@
/**
* 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 NRF_TWI_MNGR_H__
#define NRF_TWI_MNGR_H__
#include <stdint.h>
#include "nrf_drv_twi.h"
#include "sdk_errors.h"
#include "nrf_queue.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup nrf_twi_mngr TWI transaction manager
* @{
* @ingroup app_common
*
* @brief Module for scheduling TWI transactions.
*/
//If TWIM is present buffers can only be in RAM
/*lint -save -e491*/
/**
* @brief Macro checking if buffers should be stored in RAM.
*/
#ifndef NRF_TWI_MNGR_BUFFERS_IN_RAM
#define NRF_TWI_MNGR_BUFFERS_IN_RAM defined(TWIM_PRESENT)
#endif
/**
* @brief Modifier used in array declaration for TWI Manager.
*
* @note For TWI peripheral array can be const, for TWIM array has to be located in RAM.
*/
#if NRF_TWI_MNGR_BUFFERS_IN_RAM
#define NRF_TWI_MNGR_BUFFER_LOC_IND
#else
#define NRF_TWI_MNGR_BUFFER_LOC_IND const
#endif
/*lint -restore*/
/**
* @brief Flag indicating that a given transfer should not be ended
* with a stop condition.
*
* Use this flag when a stop condition is undesirable between two transfers,
* for example, when the first transfer is a write that sets an address in the slave
* device and the second one is a read that fetches certain data using this
* address. In this case, the second transfer should follow directly after the
* first transfer, with a repeated start condition instead of a stop and then
* a new start condition.
*/
#define NRF_TWI_MNGR_NO_STOP 0x01
/**
* @brief Macro for creating a write transfer.
*
* @param[in] address Slave address.
* @param[in] p_data Pointer to the data to be sent.
* @param[in] length Number of bytes to transfer.
* @param[in] flags Transfer flags (see @ref NRF_TWI_MNGR_NO_STOP).
*/
#define NRF_TWI_MNGR_WRITE(address, p_data, length, flags) \
NRF_TWI_MNGR_TRANSFER(NRF_TWI_MNGR_WRITE_OP(address), p_data, length, flags)
/**
* @brief Macro for creating a read transfer.
*
* @param address Slave address.
* @param[in] p_data Pointer to the buffer where received data should be placed.
* @param length Number of bytes to transfer.
* @param flags Transfer flags (see @ref NRF_TWI_MNGR_NO_STOP).
*/
#define NRF_TWI_MNGR_READ(address, p_data, length, flags) \
NRF_TWI_MNGR_TRANSFER(NRF_TWI_MNGR_READ_OP(address), p_data, length, flags)
/**
* @brief Helper macro, should not be used directly.
*/
#define NRF_TWI_MNGR_TRANSFER(_operation, _p_data, _length, _flags) \
{ \
.p_data = (uint8_t *)(_p_data), \
.length = _length, \
.operation = _operation, \
.flags = _flags \
}
/**
* @brief Helper macro, should not be used directly.
*/
#define NRF_TWI_MNGR_WRITE_OP(address) (((address) << 1) | 0)
/**
* @brief Helper macro, should not be used directly.
*/
#define NRF_TWI_MNGR_READ_OP(address) (((address) << 1) | 1)
/**
* @brief Helper macro, should not be used directly.
*/
#define NRF_TWI_MNGR_IS_READ_OP(operation) ((operation) & 1)
/**
* @brief Helper macro, should not be used directly.
*/
#define NRF_TWI_MNGR_OP_ADDRESS(operation) ((operation) >> 1)
/**
* @brief TWI transaction callback prototype.
*
* @param result Result of operation (NRF_SUCCESS on success,
* otherwise a relevant error code).
* @param[in] p_user_data Pointer to user data defined in transaction
* descriptor.
*/
typedef void (* nrf_twi_mngr_callback_t)(ret_code_t result, void * p_user_data);
/**
* @brief TWI transfer descriptor.
*/
typedef struct {
uint8_t * p_data; ///< Pointer to the buffer holding the data.
uint8_t length; ///< Number of bytes to transfer.
uint8_t operation; ///< Device address combined with transfer direction.
uint8_t flags; ///< Transfer flags (see @ref NRF_TWI_MNGR_NO_STOP).
} nrf_twi_mngr_transfer_t;
/**
* @brief TWI transaction descriptor.
*/
typedef struct {
nrf_twi_mngr_callback_t callback;
///< User-specified function to be called after the transaction is finished.
void * p_user_data;
///< Pointer to user data to be passed to the callback.
nrf_twi_mngr_transfer_t const * p_transfers;
///< Pointer to the array of transfers that make up the transaction.
uint8_t number_of_transfers;
///< Number of transfers that make up the transaction.
nrf_drv_twi_config_t const * p_required_twi_cfg;
///< Pointer to instance hardware configuration.
} nrf_twi_mngr_transaction_t;
/**
* @brief TWI instance control block.
*/
typedef struct {
nrf_twi_mngr_transaction_t const * volatile p_current_transaction;
///< Currently realized transaction.
nrf_drv_twi_config_t default_configuration;
///< Default hardware configuration.
nrf_drv_twi_config_t const * p_current_configuration;
///< Pointer to current hardware configuration.
uint8_t volatile current_transfer_idx;
///< Index of currently performed transfer (within current transaction).
} nrf_twi_mngr_cb_t;
/**
* @brief TWI transaction manager instance.
*/
typedef struct {
nrf_twi_mngr_cb_t * p_nrf_twi_mngr_cb;
///< Control block of instance.
nrf_queue_t const * p_queue;
///< Transaction queue.
nrf_drv_twi_t twi;
///< Pointer to TWI master driver instance.
} nrf_twi_mngr_t;
/**
* @brief Macro that simplifies defining a TWI transaction manager
* instance.
*
* This macro allocates a static buffer for the transaction queue.
* Therefore, it should be used in only one place in the code for a given
* instance.
*
* @note The queue size is the maximum number of pending transactions
* not counting the one that is currently realized. This means that
* for an empty queue with size of, for example, 4 elements, it is
* possible to schedule up to 5 transactions.
*
* @param[in] _nrf_twi_mngr_name Name of instance to be created.
* @param[in] _queue_size Size of the transaction queue (maximum number
* of pending transactions).
* @param[in] _twi_idx Index of hardware TWI instance to be used.
*/
#define NRF_TWI_MNGR_DEF(_nrf_twi_mngr_name, _queue_size, _twi_idx) \
NRF_QUEUE_DEF(nrf_twi_mngr_transaction_t const *, \
_nrf_twi_mngr_name##_queue, \
(_queue_size), \
NRF_QUEUE_MODE_NO_OVERFLOW); \
static nrf_twi_mngr_cb_t CONCAT_2(_nrf_twi_mngr_name, _cb); \
static const nrf_twi_mngr_t _nrf_twi_mngr_name = \
{ \
.p_nrf_twi_mngr_cb = &CONCAT_2(_nrf_twi_mngr_name, _cb), \
.p_queue = &_nrf_twi_mngr_name##_queue, \
.twi = NRF_DRV_TWI_INSTANCE(_twi_idx) \
}
/**
* @brief Function for initializing a TWI transaction manager instance.
*
* @param[in] p_nrf_twi_mngr Pointer to the instance to be initialized.
* @param[in] p_default_twi_config Pointer to the TWI master driver configuration. This configuration
* will be used whenever the scheduled transaction will have
* p_twi_configuration set to NULL value.
*
* @return Values returned by the @ref nrf_drv_twi_init function.
*/
ret_code_t nrf_twi_mngr_init(nrf_twi_mngr_t const * p_nrf_twi_mngr,
nrf_drv_twi_config_t const * p_default_twi_config);
/**
* @brief Function for uninitializing a TWI transaction manager instance.
*
* @param[in] p_nrf_twi_mngr Pointer to the instance to be uninitialized.
*/
void nrf_twi_mngr_uninit(nrf_twi_mngr_t const * p_nrf_twi_mngr);
/**
* @brief Function for scheduling a TWI transaction.
*
* The transaction is enqueued and started as soon as the TWI bus is
* available, thus when all previously scheduled transactions have been
* finished (possibly immediately).
*
* @note If @ref nrf_twi_mngr_transaction_t::p_required_twi_cfg
* is set to a non-NULL value the module will compare it with
* @ref nrf_twi_mngr_cb_t::p_current_configuration and reinitialize hardware
* TWI instance with new parameters if any differences are found.
* If @ref nrf_twi_mngr_transaction_t::p_required_twi_cfg is set to NULL then
* it will treat it as it would be set to @ref nrf_twi_mngr_cb_t::default_configuration.
*
* @param[in] p_nrf_twi_mngr Pointer to the TWI transaction manager instance.
* @param[in] p_transaction Pointer to the descriptor of the transaction to be
* scheduled.
*
* @retval NRF_SUCCESS If the transaction has been successfully scheduled.
* @retval NRF_ERROR_NO_MEM If the queue is full (Only if queue in
* @ref NRF_QUEUE_MODE_NO_OVERFLOW).
*/
ret_code_t nrf_twi_mngr_schedule(nrf_twi_mngr_t const * p_nrf_twi_mngr,
nrf_twi_mngr_transaction_t const * p_transaction);
/**
* @brief Function for scheduling a transaction and waiting until it is finished.
*
* This function schedules a transaction that consists of one or more transfers
* and waits until it is finished.
*
* @param[in] p_nrf_twi_mngr Pointer to the TWI transaction manager instance.
* @param[in] p_config Required TWI configuration.
* @param[in] p_transfers Pointer to an array of transfers to be performed.
* @param number_of_transfers Number of transfers to be performed.
* @param user_function User-specified function to be called while
* waiting. NULL if such functionality
* is not needed.
*
* @retval NRF_SUCCESS If the transfers have been successfully realized.
* @retval NRF_ERROR_BUSY If some transfers are already being performed.
* @retval - Other error codes mean that the transaction has ended
* with the error that is specified in the error code.
*/
ret_code_t nrf_twi_mngr_perform(nrf_twi_mngr_t const * p_nrf_twi_mngr,
nrf_drv_twi_config_t const * p_config,
nrf_twi_mngr_transfer_t const * p_transfers,
uint8_t number_of_transfers,
void (* user_function)(void));
/**
* @brief Function for getting the current state of a TWI transaction manager
* instance.
*
* @param[in] p_nrf_twi_mngr Pointer to the TWI transaction manager instance.
*
* @retval true If all scheduled transactions have been finished.
* @retval false Otherwise.
*/
__STATIC_INLINE bool nrf_twi_mngr_is_idle(nrf_twi_mngr_t const * p_nrf_twi_mngr);
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE bool nrf_twi_mngr_is_idle(nrf_twi_mngr_t const * p_nrf_twi_mngr)
{
return (p_nrf_twi_mngr->p_nrf_twi_mngr_cb->p_current_transaction == NULL);
}
#endif //SUPPRESS_INLINE_IMPLEMENTATION
/**
*@}
**/
#ifdef __cplusplus
}
#endif
#endif // NRF_TWI_MNGR_H__

View File

@ -0,0 +1,125 @@
/**
* Copyright (c) 2014 - 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 app_error Common application error handler
* @{
* @ingroup app_common
*
* @brief Common application error handler.
*/
#include "nrf.h"
#include <stdio.h>
#include "app_error.h"
#include "nordic_common.h"
#include "sdk_errors.h"
/**@brief Function for error handling, which is called when an error has occurred.
*
* @warning This handler is an example only and does not fit a final product. You need to analyze
* how your product is supposed to react in case of error.
*
* @param[in] error_code Error code supplied to the handler.
* @param[in] line_num Line number where the handler is called.
* @param[in] p_file_name Pointer to the file name.
*/
void app_error_handler_bare(ret_code_t error_code)
{
error_info_t error_info =
{
.line_num = 0,
.p_file_name = NULL,
.err_code = error_code,
};
app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info));
UNUSED_VARIABLE(error_info);
}
void app_error_save_and_stop(uint32_t id, uint32_t pc, uint32_t info)
{
/* static error variables - in order to prevent removal by optimizers */
static volatile struct
{
uint32_t fault_id;
uint32_t pc;
uint32_t error_info;
assert_info_t * p_assert_info;
error_info_t * p_error_info;
ret_code_t err_code;
uint32_t line_num;
const uint8_t * p_file_name;
} m_error_data = {0};
// The following variable helps Keil keep the call stack visible, in addition, it can be set to
// 0 in the debugger to continue executing code after the error check.
volatile bool loop = true;
UNUSED_VARIABLE(loop);
m_error_data.fault_id = id;
m_error_data.pc = pc;
m_error_data.error_info = info;
switch (id)
{
case NRF_FAULT_ID_SDK_ASSERT:
m_error_data.p_assert_info = (assert_info_t *)info;
m_error_data.line_num = m_error_data.p_assert_info->line_num;
m_error_data.p_file_name = m_error_data.p_assert_info->p_file_name;
break;
case NRF_FAULT_ID_SDK_ERROR:
m_error_data.p_error_info = (error_info_t *)info;
m_error_data.err_code = m_error_data.p_error_info->err_code;
m_error_data.line_num = m_error_data.p_error_info->line_num;
m_error_data.p_file_name = m_error_data.p_error_info->p_file_name;
break;
}
UNUSED_VARIABLE(m_error_data);
// If printing is disrupted, remove the irq calls, or set the loop variable to 0 in the debugger.
__disable_irq();
while (loop);
__enable_irq();
}

View File

@ -0,0 +1,192 @@
/**
* Copyright (c) 2013 - 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 app_error Common application error handler
* @{
* @ingroup app_common
*
* @brief Common application error handler and macros for utilizing a common error handler.
*/
#ifndef APP_ERROR_H__
#define APP_ERROR_H__
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include "nrf.h"
#include "sdk_errors.h"
#include "nordic_common.h"
#include "app_error_weak.h"
#ifdef ANT_STACK_SUPPORT_REQD
#include "ant_error.h"
#endif // ANT_STACK_SUPPORT_REQD
#ifdef __cplusplus
extern "C" {
#endif
#define NRF_FAULT_ID_SDK_RANGE_START (0x00004000) /**< The start of the range of error IDs defined in the SDK. */
/**@defgroup APP_ERROR_FAULT_IDS Fault ID types
* @{ */
#define NRF_FAULT_ID_SDK_ERROR (NRF_FAULT_ID_SDK_RANGE_START + 1) /**< An error stemming from a call to @ref APP_ERROR_CHECK or @ref APP_ERROR_CHECK_BOOL. The info parameter is a pointer to an @ref error_info_t variable. */
#define NRF_FAULT_ID_SDK_ASSERT (NRF_FAULT_ID_SDK_RANGE_START + 2) /**< An error stemming from a call to ASSERT (nrf_assert.h). The info parameter is a pointer to an @ref assert_info_t variable. */
/**@} */
/**@brief Structure containing info about an error of the type @ref NRF_FAULT_ID_SDK_ERROR.
*/
typedef struct
{
uint32_t line_num; /**< The line number where the error occurred. */
uint8_t const * p_file_name; /**< The file in which the error occurred. */
uint32_t err_code; /**< The error code representing the error that occurred. */
} error_info_t;
/**@brief Structure containing info about an error of the type @ref NRF_FAULT_ID_SDK_ASSERT.
*/
typedef struct
{
uint16_t line_num; /**< The line number where the error occurred. */
uint8_t const * p_file_name; /**< The file in which the error occurred. */
} assert_info_t;
/**@brief Defines required by app_error_handler assembler intructions.
*/
#define APP_ERROR_ERROR_INFO_OFFSET_LINE_NUM (offsetof(error_info_t, line_num))
#define APP_ERROR_ERROR_INFO_OFFSET_P_FILE_NAME (offsetof(error_info_t, p_file_name))
#define APP_ERROR_ERROR_INFO_OFFSET_ERR_CODE (offsetof(error_info_t, err_code))
#define APP_ERROR_ERROR_INFO_SIZE (sizeof(error_info_t))
#define APP_ERROR_ERROR_INFO_SIZE_ALIGNED_8BYTE \
ALIGN_NUM(APP_ERROR_ERROR_INFO_SIZE, sizeof(uint64_t))
/**@brief Function for error handling, which is called when an error has occurred.
*
* @param[in] error_code Error code supplied to the handler.
* @param[in] line_num Line number where the handler is called.
* @param[in] p_file_name Pointer to the file name.
*/
void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name);
/**@brief Function for error handling, which is called when an error has occurred.
*
* @param[in] error_code Error code supplied to the handler.
*/
void app_error_handler_bare(ret_code_t error_code);
/**@brief Function for saving the parameters and entering an eternal loop, for debug purposes.
*
* @param[in] id Fault identifier. See @ref NRF_FAULT_IDS.
* @param[in] pc The program counter of the instruction that triggered the fault, or 0 if
* unavailable.
* @param[in] info Optional additional information regarding the fault. Refer to each fault
* identifier for details.
*/
void app_error_save_and_stop(uint32_t id, uint32_t pc, uint32_t info);
/**@brief Function for logging details of error and flushing logs.
*
* @param[in] id Fault identifier. See @ref NRF_FAULT_IDS.
* @param[in] pc The program counter of the instruction that triggered the fault, or 0 if
* unavailable.
* @param[in] info Optional additional information regarding the fault. Refer to each fault
* identifier for details.
*/
void app_error_log_handle(uint32_t id, uint32_t pc, uint32_t info);
/**@brief Macro for calling error handler function.
*
* @param[in] ERR_CODE Error code supplied to the error handler.
*/
#ifdef DEBUG
#define APP_ERROR_HANDLER(ERR_CODE) \
do \
{ \
app_error_handler((ERR_CODE), __LINE__, (uint8_t*) __FILE__); \
} while (0)
#else
#define APP_ERROR_HANDLER(ERR_CODE) \
do \
{ \
app_error_handler_bare((ERR_CODE)); \
} while (0)
#endif
/**@brief Macro for calling error handler function if supplied error code any other than NRF_SUCCESS.
*
* @param[in] ERR_CODE Error code supplied to the error handler.
*/
#define APP_ERROR_CHECK(ERR_CODE) \
do \
{ \
const uint32_t LOCAL_ERR_CODE = (ERR_CODE); \
if (LOCAL_ERR_CODE != NRF_SUCCESS) \
{ \
APP_ERROR_HANDLER(LOCAL_ERR_CODE); \
} \
} while (0)
/**@brief Macro for calling error handler function if supplied boolean value is false.
*
* @param[in] BOOLEAN_VALUE Boolean value to be evaluated.
*/
#define APP_ERROR_CHECK_BOOL(BOOLEAN_VALUE) \
do \
{ \
const uint32_t LOCAL_BOOLEAN_VALUE = (BOOLEAN_VALUE); \
if (!LOCAL_BOOLEAN_VALUE) \
{ \
APP_ERROR_HANDLER(0); \
} \
} while (0)
#ifdef __cplusplus
}
#endif
#endif // APP_ERROR_H__
/** @} */

View File

@ -0,0 +1,105 @@
/**
* 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"
#include "compiler_abstraction.h"
#include "app_error.h"
// only compile this if we are using GCC
#if defined (__GNUC__) && !defined (__CC_ARM)
#if defined (__CORTEX_M) && (__CORTEX_M == 0x04)
void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name) __attribute__(( naked ));
void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name)
{
__ASM volatile(
"push {lr} \n"
/* reserve space on stack for error_info_t struct - preserve 8byte stack aligment */
"sub sp, sp, %0 \n"
/* prepare error_info_t struct */
"str r0, [sp, %1] \n"
"str r1, [sp, %3] \n"
"str r2, [sp, %2] \n"
/* prepare arguments and call function: app_error_fault_handler */
"ldr r0, =%4 \n"
"mov r1, lr \n"
"mov r2, sp \n"
"bl %5 \n"
/* release stack */
"add sp, sp, %0 \n"
"pop {pc} \n"
".ltorg \n"
: /* Outputs */
: /* Inputs */
"I" (APP_ERROR_ERROR_INFO_SIZE_ALIGNED_8BYTE),
"I" (APP_ERROR_ERROR_INFO_OFFSET_ERR_CODE),
"I" (APP_ERROR_ERROR_INFO_OFFSET_P_FILE_NAME),
"I" (APP_ERROR_ERROR_INFO_OFFSET_LINE_NUM),
"X" (NRF_FAULT_ID_SDK_ERROR),
"X" (app_error_fault_handler)
: /* Clobbers */
"r0", "r1", "r2"
);
}
#elif defined(__CORTEX_M) && (__CORTEX_M == 0x00)
/* NRF51 implementation is currently not supporting PC readout */
void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name)
{
error_info_t error_info = {
.line_num = line_num,
.p_file_name = p_file_name,
.err_code = error_code,
};
app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info));
UNUSED_VARIABLE(error_info);
}
#else
#error Architecture not supported
#endif
#endif

View File

@ -0,0 +1,105 @@
/**
* 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"
#include "compiler_abstraction.h"
#include "app_error.h"
// Build this only if compiling with IAR!
#if defined ( __ICCARM__ )
#if defined (__CORTEX_M) && (__CORTEX_M == 0x04)
void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name)
{
__ASM volatile(
"push {lr} \n"
/* reserve space on stack for error_info_t struct */
"sub sp, sp, %0 \n"
/* prepare error_info_t struct */
"str r0, [sp, %1] \n"
"str r1, [sp, %3] \n"
"str r2, [sp, %2] \n"
/* prepare arguments and call function: app_error_fault_handler */
"ldr.n r0, 1f \n"
"mov r1, LR \n"
"mov r2, sp \n"
/* call app_error_fault_handler */
"bl %c5 \n"
/* release stack */
"add sp, sp, %0 \n"
"pop {pc} \n"
"DATA \n"
"1: \n"
" DC32 %c4 \n"
: /* Outputs */
: /* Inputs */
"i" (APP_ERROR_ERROR_INFO_SIZE_ALIGNED_8BYTE),
"i" (APP_ERROR_ERROR_INFO_OFFSET_ERR_CODE),
"i" (APP_ERROR_ERROR_INFO_OFFSET_P_FILE_NAME),
"i" (APP_ERROR_ERROR_INFO_OFFSET_LINE_NUM),
"i" (NRF_FAULT_ID_SDK_ERROR),
"i" (app_error_fault_handler)
: /* CLobbers */
"r0", "r1", "r2"
);
}
#elif defined(__CORTEX_M) && (__CORTEX_M == 0x00)
/* NRF51 implementation is currently not supporting PC readout */
void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name)
{
error_info_t error_info = {
.line_num = line_num,
.p_file_name = p_file_name,
.err_code = error_code,
};
app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info));
UNUSED_VARIABLE(error_info);
}
#else
#error Architecture not supported
#endif
#endif

View File

@ -0,0 +1,96 @@
/**
* 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"
#include "compiler_abstraction.h"
#include "app_error.h"
// make sure we are using armcc!
#if defined (__CC_ARM)
#if defined (__CORTEX_M) && (__CORTEX_M == 0x04)
__ASM void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name)
{
PRESERVE8 {TRUE}
THUMB
push {lr}
/* reserve space on stack for error_info_t struct - preserve 8byte stack aligment */
sub sp, sp, #__cpp(APP_ERROR_ERROR_INFO_SIZE_ALIGNED_8BYTE)
/* prepare error_info_t struct */
str r0, [sp, #__cpp(APP_ERROR_ERROR_INFO_OFFSET_ERR_CODE)]
str r1, [sp, #__cpp(APP_ERROR_ERROR_INFO_OFFSET_LINE_NUM)]
str r2, [sp, #__cpp(APP_ERROR_ERROR_INFO_OFFSET_P_FILE_NAME)]
/* prepare arguments and call function: app_error_fault_handler */
mov r0, #__cpp(NRF_FAULT_ID_SDK_ERROR)
mov r1, lr
mov r2, sp
/* call function */
bl __cpp(app_error_fault_handler)
/* release stack */
add sp, sp, #__cpp(APP_ERROR_ERROR_INFO_SIZE_ALIGNED_8BYTE)
pop {pc}
}
#elif defined(__CORTEX_M) && (__CORTEX_M == 0x00)
/* NRF51 implementation is currently not supporting PC readout */
void app_error_handler(ret_code_t error_code, uint32_t line_num, const uint8_t * p_file_name)
{
error_info_t error_info = {
.line_num = line_num,
.p_file_name = p_file_name,
.err_code = error_code,
};
app_error_fault_handler(NRF_FAULT_ID_SDK_ERROR, 0, (uint32_t)(&error_info));
UNUSED_VARIABLE(error_info);
}
#else
#error Architecture not supported
#endif
#endif

View File

@ -0,0 +1,109 @@
/**
* Copyright (c) 2016 - 2018, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "app_error.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_strerror.h"
#if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT
#include "nrf_sdm.h"
#endif
/*lint -save -e14 */
/**
* Function is implemented as weak so that it can be overwritten by custom application error handler
* when needed.
*/
__WEAK void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info)
{
__disable_irq();
NRF_LOG_FINAL_FLUSH();
#ifndef DEBUG
NRF_LOG_ERROR("Fatal error");
#else
switch (id)
{
#if defined(SOFTDEVICE_PRESENT) && SOFTDEVICE_PRESENT
case NRF_FAULT_ID_SD_ASSERT:
NRF_LOG_ERROR("SOFTDEVICE: ASSERTION FAILED");
break;
case NRF_FAULT_ID_APP_MEMACC:
NRF_LOG_ERROR("SOFTDEVICE: INVALID MEMORY ACCESS");
break;
#endif
case NRF_FAULT_ID_SDK_ASSERT:
{
assert_info_t * p_info = (assert_info_t *)info;
NRF_LOG_ERROR("ASSERTION FAILED at %s:%u",
p_info->p_file_name,
p_info->line_num);
break;
}
case NRF_FAULT_ID_SDK_ERROR:
{
error_info_t * p_info = (error_info_t *)info;
NRF_LOG_ERROR("ERROR %u [%s] at %s:%u\r\nPC at: 0x%08x",
p_info->err_code,
nrf_strerror_get(p_info->err_code),
p_info->p_file_name,
p_info->line_num,
pc);
NRF_LOG_ERROR("End of error report");
break;
}
default:
NRF_LOG_ERROR("UNKNOWN FAULT at 0x%08X", pc);
break;
}
#endif
NRF_BREAKPOINT_COND;
// On assert, the system can only recover with a reset.
#ifndef DEBUG
NRF_LOG_WARNING("System reset");
NVIC_SystemReset();
#else
app_error_save_and_stop(id, pc, info);
#endif // DEBUG
}
/*lint -restore */

View File

@ -0,0 +1,87 @@
/**
* 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.
*
*/
#ifndef APP_ERROR_WEAK_H__
#define APP_ERROR_WEAK_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/** @file
*
* @defgroup app_error Common application error handler
* @{
* @ingroup app_common
*
* @brief Common application error handler.
*/
/**@brief Callback function for errors, asserts, and faults.
*
* @details This function is called every time an error is raised in app_error, nrf_assert, or
* in the SoftDevice. Information about the error can be found in the @p info
* parameter.
*
* See also @ref nrf_fault_handler_t for more details.
*
* @note The function is implemented as weak so that it can be redefined by a custom error
* handler when needed.
*
* @param[in] id Fault identifier. See @ref NRF_FAULT_IDS.
* @param[in] pc The program counter of the instruction that triggered the fault, or 0 if
* unavailable.
* @param[in] info Optional additional information regarding the fault. The value of the @p id
* parameter dictates how to interpret this parameter. Refer to the documentation
* for each fault identifier (@ref NRF_FAULT_IDS and @ref APP_ERROR_FAULT_IDS) for
* details about interpreting @p info.
*/
void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info);
/** @} */
#ifdef __cplusplus
}
#endif
#endif // APP_ERROR_WEAK_H__

View File

@ -0,0 +1,449 @@
/**
* 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 app_util Utility Functions and Definitions
* @{
* @ingroup app_common
*
* @brief Various types and definitions available to all applications.
*/
#ifndef APP_UTIL_BDS_H__
#define APP_UTIL_BDS_H__
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include "compiler_abstraction.h"
#include "app_util.h"
#include "ble_srv_common.h"
#include "nordic_common.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef uint8_t nibble_t;
typedef uint32_t uint24_t;
typedef uint64_t uint40_t;
/**@brief IEEE 11073-20601 Regulatory Certification Data List Structure */
typedef struct
{
uint8_t * p_list; /**< Pointer the byte array containing the encoded opaque structure based on IEEE 11073-20601 specification. */
uint8_t list_len; /**< Length of the byte array. */
} regcertdatalist_t;
/**@brief SFLOAT format (IEEE-11073 16-bit FLOAT, meaning 4 bits for exponent (base 10) and 12 bits mantissa) */
typedef struct
{
int8_t exponent; /**< Base 10 exponent, should be using only 4 bits */
int16_t mantissa; /**< Mantissa, should be using only 12 bits */
} sfloat_t;
/**@brief Date and Time structure. */
typedef struct
{
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hours;
uint8_t minutes;
uint8_t seconds;
} ble_date_time_t;
/**@brief Function for encoding a uint16 value.
*
* @param[in] p_value Value to be encoded.
* @param[out] p_encoded_data Buffer where the encoded data is to be written.
*
* @return Number of bytes written.
*/
static __INLINE uint8_t bds_uint16_encode(const uint16_t * p_value, uint8_t * p_encoded_data)
{
p_encoded_data[0] = (uint8_t) ((*p_value & 0x00FF) >> 0);
p_encoded_data[1] = (uint8_t) ((*p_value & 0xFF00) >> 8);
return sizeof(uint16_t);
}
static __INLINE uint8_t bds_int16_encode(const int16_t * p_value, uint8_t * p_encoded_data)
{
uint16_t tmp = *p_value;
return bds_uint16_encode(&tmp, p_encoded_data);
}
/**@brief Function for encoding a uint24 value.
*
* @param[in] p_value Value to be encoded.
* @param[out] p_encoded_data Buffer where the encoded data is to be written.
*
* @return Number of bytes written.
*/
static __INLINE uint8_t bds_uint24_encode(const uint32_t * p_value, uint8_t * p_encoded_data)
{
p_encoded_data[0] = (uint8_t) ((*p_value & 0x000000FF) >> 0);
p_encoded_data[1] = (uint8_t) ((*p_value & 0x0000FF00) >> 8);
p_encoded_data[2] = (uint8_t) ((*p_value & 0x00FF0000) >> 16);
return (3);
}
/**@brief Function for encoding a uint32 value.
*
* @param[in] p_value Value to be encoded.
* @param[out] p_encoded_data Buffer where the encoded data is to be written.
*
* @return Number of bytes written.
*/
static __INLINE uint8_t bds_uint32_encode(const uint32_t * p_value, uint8_t * p_encoded_data)
{
p_encoded_data[0] = (uint8_t) ((*p_value & 0x000000FF) >> 0);
p_encoded_data[1] = (uint8_t) ((*p_value & 0x0000FF00) >> 8);
p_encoded_data[2] = (uint8_t) ((*p_value & 0x00FF0000) >> 16);
p_encoded_data[3] = (uint8_t) ((*p_value & 0xFF000000) >> 24);
return sizeof(uint32_t);
}
/**@brief Function for encoding a uint40 value.
*
* @param[in] p_value Value to be encoded.
* @param[out] p_encoded_data Buffer where the encoded data is to be written.
*
* @return Number of bytes written.
*/
static __INLINE uint8_t bds_uint40_encode(const uint64_t * p_value, uint8_t * p_encoded_data)
{
p_encoded_data[0] = (uint8_t) ((*p_value & 0x00000000000000FF) >> 0);
p_encoded_data[1] = (uint8_t) ((*p_value & 0x000000000000FF00) >> 8);
p_encoded_data[2] = (uint8_t) ((*p_value & 0x0000000000FF0000) >> 16);
p_encoded_data[3] = (uint8_t) ((*p_value & 0x00000000FF000000) >> 24);
p_encoded_data[4] = (uint8_t) ((*p_value & 0x000000FF00000000) >> 32);
return 5;
}
/**@brief Function for encoding a sfloat value.
*
* @param[in] p_value Value to be encoded.
* @param[out] p_encoded_data Buffer where the encoded data is to be written.
*
* @return Number of bytes written.
*/
static __INLINE uint8_t bds_sfloat_encode(const sfloat_t * p_value, uint8_t * p_encoded_data)
{
uint16_t encoded_val;
encoded_val = ((p_value->exponent << 12) & 0xF000) |
((p_value->mantissa << 0) & 0x0FFF);
return(bds_uint16_encode(&encoded_val, p_encoded_data));
}
/**@brief Function for encoding a uint8_array value.
*
* @param[in] p_value Value to be encoded.
* @param[out] p_encoded_data Buffer where the encoded data is to be written.
*/
static __INLINE uint8_t bds_uint8_array_encode(const uint8_array_t * p_value,
uint8_t * p_encoded_data)
{
memcpy(p_encoded_data, p_value->p_data, p_value->size);
return p_value->size;
}
/**@brief Function for encoding a utf8_str value.
*
* @param[in] p_value Value to be encoded.
* @param[out] p_encoded_data Buffer where the encoded data is to be written.
*/
static __INLINE uint8_t bds_ble_srv_utf8_str_encode(const ble_srv_utf8_str_t * p_value,
uint8_t * p_encoded_data)
{
memcpy(p_encoded_data, p_value->p_str, p_value->length);
return p_value->length;
}
/**@brief Function for encoding a regcertdatalist value.
*
* @param[in] p_value Value to be encoded.
* @param[out] p_encoded_data Buffer where the encoded data is to be written.
*/
static __INLINE uint8_t bds_regcertdatalist_encode(const regcertdatalist_t * p_value,
uint8_t * p_encoded_data)
{
memcpy(p_encoded_data, p_value->p_list, p_value->list_len);
return p_value->list_len;
}
/**@brief Function for decoding a date_time value.
*
* @param[in] p_date_time pointer to the date_time structure to encode.
* @param[in] p_encoded_data pointer to the encoded data
* @return length of the encoded field.
*/
static __INLINE uint8_t bds_ble_date_time_encode(const ble_date_time_t * p_date_time,
uint8_t * p_encoded_data)
{
uint8_t len = bds_uint16_encode(&p_date_time->year, &p_encoded_data[0]);
p_encoded_data[len++] = p_date_time->month;
p_encoded_data[len++] = p_date_time->day;
p_encoded_data[len++] = p_date_time->hours;
p_encoded_data[len++] = p_date_time->minutes;
p_encoded_data[len++] = p_date_time->seconds;
return len;
}
/**@brief Function for decoding a uint16 value.
*
* @param[in] len length of the field to be decoded.
* @param[in] p_encoded_data Buffer where the encoded data is stored.
* @param[in] p_decoded_val pointer to the decoded value
* @return length of the decoded field.
*/
static __INLINE uint8_t bds_uint16_decode(const uint8_t len,
const uint8_t * p_encoded_data,
uint16_t * p_decoded_val)
{
UNUSED_VARIABLE(len);
*p_decoded_val = (((uint16_t)((uint8_t *)p_encoded_data)[0])) |
(((uint16_t)((uint8_t *)p_encoded_data)[1]) << 8 );
return (sizeof(uint16_t));
}
/**@brief Function for decoding a int16 value.
*
* @param[in] len length of the field to be decoded.
* @param[in] p_encoded_data Buffer where the encoded data is stored.
* @param[in] p_decoded_val pointer to the decoded value
* @return length of the decoded field.
*/
static __INLINE uint8_t bds_int16_decode(const uint8_t len,
const uint8_t * p_encoded_data,
int16_t * p_decoded_val)
{
UNUSED_VARIABLE(len);
uint16_t tmp = 0;
uint8_t retval = bds_uint16_decode(len, p_encoded_data, &tmp);
*p_decoded_val = (int16_t)tmp;
return retval;
}
/**@brief Function for decoding a uint24 value.
*
* @param[in] len length of the field to be decoded.
* @param[in] p_encoded_data Buffer where the encoded data is stored.
* @param[in] p_decoded_val pointer to the decoded value
*
* @return length of the decoded field.
*/
static __INLINE uint8_t bds_uint24_decode(const uint8_t len,
const uint8_t * p_encoded_data,
uint32_t * p_decoded_val)
{
UNUSED_VARIABLE(len);
*p_decoded_val = (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) |
(((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) |
(((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16);
return (3);
}
/**@brief Function for decoding a uint32 value.
*
* @param[in] len length of the field to be decoded.
* @param[in] p_encoded_data Buffer where the encoded data is stored.
* @param[in] p_decoded_val pointer to the decoded value
*
* @return length of the decoded field.
*/
static __INLINE uint8_t bds_uint32_decode(const uint8_t len,
const uint8_t * p_encoded_data,
uint32_t * p_decoded_val)
{
UNUSED_VARIABLE(len);
*p_decoded_val = (((uint32_t)((uint8_t *)p_encoded_data)[0]) << 0) |
(((uint32_t)((uint8_t *)p_encoded_data)[1]) << 8) |
(((uint32_t)((uint8_t *)p_encoded_data)[2]) << 16) |
(((uint32_t)((uint8_t *)p_encoded_data)[3]) << 24 );
return (sizeof(uint32_t));
}
/**@brief Function for decoding a uint40 value.
*
* @param[in] len length of the field to be decoded.
* @param[in] p_encoded_data Buffer where the encoded data is stored.
* @param[in] p_decoded_val pointer to the decoded value
*
* @return length of the decoded field.
*/
static __INLINE uint8_t bds_uint40_decode(const uint8_t len,
const uint8_t * p_encoded_data,
uint64_t * p_decoded_val)
{
UNUSED_VARIABLE(len);
*p_decoded_val = (((uint64_t)((uint8_t *)p_encoded_data)[0]) << 0) |
(((uint64_t)((uint8_t *)p_encoded_data)[1]) << 8) |
(((uint64_t)((uint8_t *)p_encoded_data)[2]) << 16) |
(((uint64_t)((uint8_t *)p_encoded_data)[3]) << 24 )|
(((uint64_t)((uint8_t *)p_encoded_data)[4]) << 32 );
return (40);
}
/**@brief Function for decoding a sfloat value.
*
* @param[in] len length of the field to be decoded.
* @param[in] p_encoded_data Buffer where the encoded data is stored.
* @param[in] p_decoded_val pointer to the decoded value
*
* @return length of the decoded field.
*/
static __INLINE uint8_t bds_sfloat_decode(const uint8_t len,
const uint8_t * p_encoded_data,
sfloat_t * p_decoded_val)
{
p_decoded_val->exponent = 0;
bds_uint16_decode(len, p_encoded_data, (uint16_t*)&p_decoded_val->mantissa);
p_decoded_val->exponent = (uint8_t)((p_decoded_val->mantissa & 0xF000) >> 12);
p_decoded_val->mantissa &= 0x0FFF;
return len;
}
/**@brief Function for decoding a uint8_array value.
*
* @param[in] len length of the field to be decoded.
* @param[in] p_encoded_data Buffer where the encoded data is stored.
* @param[in] p_decoded_val pointer to the decoded value
*
* @return length of the decoded field.
*/
static __INLINE uint8_t bds_uint8_array_decode(const uint8_t len,
const uint8_t * p_encoded_data,
uint8_array_t * p_decoded_val)
{
memcpy(p_decoded_val->p_data, p_encoded_data, len);
p_decoded_val->size = len;
return p_decoded_val->size;
}
/**@brief Function for decoding a utf8_str value.
*
* @param[in] len length of the field to be decoded.
* @param[in] p_encoded_data Buffer where the encoded data is stored.
* @param[in] p_decoded_val pointer to the decoded value
*
* @return length of the decoded field.
*/
static __INLINE uint8_t bds_ble_srv_utf8_str_decode(const uint8_t len,
const uint8_t * p_encoded_data,
ble_srv_utf8_str_t * p_decoded_val)
{
p_decoded_val->p_str = (uint8_t*)p_encoded_data;
p_decoded_val->length = len;
return p_decoded_val->length;
}
/**@brief Function for decoding a regcertdatalist value.
*
* @param[in] len length of the field to be decoded.
* @param[in] p_encoded_data Buffer where the encoded data is stored.
* @param[in] p_decoded_val pointer to the decoded value
*
* @return length of the decoded field.
*/
static __INLINE uint8_t bds_regcertdatalist_decode(const uint8_t len,
const uint8_t * p_encoded_data,
regcertdatalist_t * p_decoded_val)
{
memcpy(p_decoded_val->p_list, p_encoded_data, len);
p_decoded_val->list_len = len;
return p_decoded_val->list_len;
}
/**@brief Function for decoding a date_time value.
*
* @param[in] len length of the field to be decoded.
* @param[in] p_encoded_data Buffer where the encoded data is stored.
* @param[in] p_date_time pointer to the decoded value
*
* @return length of the decoded field.
*/
static __INLINE uint8_t bds_ble_date_time_decode(const uint8_t len,
const uint8_t * p_encoded_data,
ble_date_time_t * p_date_time)
{
UNUSED_VARIABLE(len);
uint8_t pos = bds_uint16_decode(len, &p_encoded_data[0], &p_date_time->year);
p_date_time->month = p_encoded_data[pos++];
p_date_time->day = p_encoded_data[pos++];
p_date_time->hours = p_encoded_data[pos++];
p_date_time->minutes = p_encoded_data[pos++];
p_date_time->seconds = p_encoded_data[pos++];
return pos;
}
#ifdef __cplusplus
}
#endif
#endif // APP_UTIL_BDS_H__
/** @} */

View File

@ -0,0 +1,127 @@
/**
* Copyright (c) 2014 - 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 "app_util_platform.h"
#ifdef SOFTDEVICE_PRESENT
/* Global nvic state instance, required by nrf_nvic.h */
nrf_nvic_state_t nrf_nvic_state;
#endif
static uint32_t m_in_critical_region = 0;
void app_util_disable_irq(void)
{
__disable_irq();
m_in_critical_region++;
}
void app_util_enable_irq(void)
{
m_in_critical_region--;
if (m_in_critical_region == 0)
{
__enable_irq();
}
}
void app_util_critical_region_enter(uint8_t *p_nested)
{
#if __CORTEX_M == (0x04U)
ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get())
#endif
#if defined(SOFTDEVICE_PRESENT)
/* return value can be safely ignored */
(void) sd_nvic_critical_region_enter(p_nested);
#else
app_util_disable_irq();
#endif
}
void app_util_critical_region_exit(uint8_t nested)
{
#if __CORTEX_M == (0x04U)
ASSERT(APP_LEVEL_PRIVILEGED == privilege_level_get())
#endif
#if defined(SOFTDEVICE_PRESENT)
/* return value can be safely ignored */
(void) sd_nvic_critical_region_exit(nested);
#else
app_util_enable_irq();
#endif
}
uint8_t privilege_level_get(void)
{
#if __CORTEX_M == (0x00U) || defined(_WIN32) || defined(__unix) || defined(__APPLE__)
/* the Cortex-M0 has no concept of privilege */
return APP_LEVEL_PRIVILEGED;
#elif __CORTEX_M == (0x04U)
uint32_t isr_vector_num = __get_IPSR() & IPSR_ISR_Msk ;
if (0 == isr_vector_num)
{
/* Thread Mode, check nPRIV */
int32_t control = __get_CONTROL();
return control & CONTROL_nPRIV_Msk ? APP_LEVEL_UNPRIVILEGED : APP_LEVEL_PRIVILEGED;
}
else
{
/* Handler Mode, always privileged */
return APP_LEVEL_PRIVILEGED;
}
#endif
}
uint8_t current_int_priority_get(void)
{
uint32_t isr_vector_num = __get_IPSR() & IPSR_ISR_Msk ;
if (isr_vector_num > 0)
{
int32_t irq_type = ((int32_t)isr_vector_num - EXTERNAL_INT_VECTOR_OFFSET);
return (NVIC_GetPriority((IRQn_Type)irq_type) & 0xFF);
}
else
{
return APP_IRQ_PRIORITY_THREAD;
}
}

View File

@ -0,0 +1,279 @@
/**
* Copyright (c) 2014 - 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 app_util_platform Utility Functions and Definitions (Platform)
* @{
* @ingroup app_common
*
* @brief Various types and definitions available to all applications when using SoftDevice.
*/
#ifndef APP_UTIL_PLATFORM_H__
#define APP_UTIL_PLATFORM_H__
#include <stdint.h>
#include "compiler_abstraction.h"
#include "nrf.h"
#ifdef SOFTDEVICE_PRESENT
#include "nrf_soc.h"
#include "nrf_nvic.h"
#endif
#include "nrf_assert.h"
#include "app_error.h"
#ifdef __cplusplus
extern "C" {
#endif
#if __CORTEX_M == (0x00U)
#define _PRIO_SD_HIGH 0
#define _PRIO_APP_HIGH 1
#define _PRIO_APP_MID 1
#define _PRIO_SD_LOW 2
#define _PRIO_APP_LOW 3
#define _PRIO_APP_LOWEST 3
#define _PRIO_THREAD 4
#elif __CORTEX_M == (0x04U)
#define _PRIO_SD_HIGH 0
#define _PRIO_SD_MID 1
#define _PRIO_APP_HIGH 2
#define _PRIO_APP_MID 3
#define _PRIO_SD_LOW 4
#define _PRIO_SD_LOWEST 5
#define _PRIO_APP_LOW 6
#define _PRIO_APP_LOWEST 7
#define _PRIO_THREAD 15
#else
#error "No platform defined"
#endif
//lint -save -e113 -e452
/**@brief The interrupt priorities available to the application while the SoftDevice is active. */
typedef enum
{
#ifndef SOFTDEVICE_PRESENT
APP_IRQ_PRIORITY_HIGHEST = _PRIO_SD_HIGH,
#else
APP_IRQ_PRIORITY_HIGHEST = _PRIO_APP_HIGH,
#endif
APP_IRQ_PRIORITY_HIGH = _PRIO_APP_HIGH,
#ifndef SOFTDEVICE_PRESENT
APP_IRQ_PRIORITY_MID = _PRIO_SD_LOW,
#else
APP_IRQ_PRIORITY_MID = _PRIO_APP_MID,
#endif
APP_IRQ_PRIORITY_LOW = _PRIO_APP_LOW,
APP_IRQ_PRIORITY_LOWEST = _PRIO_APP_LOWEST,
APP_IRQ_PRIORITY_THREAD = _PRIO_THREAD /**< "Interrupt level" when running in Thread Mode. */
} app_irq_priority_t;
//lint -restore
/*@brief The privilege levels available to applications in Thread Mode */
typedef enum
{
APP_LEVEL_UNPRIVILEGED,
APP_LEVEL_PRIVILEGED
} app_level_t;
/**@cond NO_DOXYGEN */
#define EXTERNAL_INT_VECTOR_OFFSET 16
/**@endcond */
/**@brief Macro for setting a breakpoint.
*/
#if defined(__GNUC__)
#define NRF_BREAKPOINT __asm__("BKPT 0");
#else
#define NRF_BREAKPOINT __BKPT(0)
#endif
/** @brief Macro for setting a breakpoint.
*
* If it is possible to detect debugger presence then it is set only in that case.
*
*/
#if __CORTEX_M == 0x04
#define NRF_BREAKPOINT_COND do { \
/* C_DEBUGEN == 1 -> Debugger Connected */ \
if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) \
{ \
/* Generate breakpoint if debugger is connected */ \
NRF_BREAKPOINT; \
} \
}while (0)
#else
#define NRF_BREAKPOINT_COND NRF_BREAKPOINT
#endif // __CORTEX_M == 0x04
#if defined ( __CC_ARM )
#define PACKED(TYPE) __packed TYPE
#define PACKED_STRUCT PACKED(struct)
#elif defined ( __GNUC__ )
#define PACKED __attribute__((packed))
#define PACKED_STRUCT struct PACKED
#elif defined (__ICCARM__)
#define PACKED_STRUCT __packed struct
#endif
#if defined ( __CC_ARM )
#define PRAGMA_OPTIMIZATION_FORCE_START _Pragma ("push") \
_Pragma ("O3")
#define PRAGMA_OPTIMIZATION_FORCE_END _Pragma ("pop")
#elif defined ( __GNUC__ )
#define PRAGMA_OPTIMIZATION_FORCE_START _Pragma("GCC push_options") \
_Pragma ("GCC optimize (\"Os\")")
#define PRAGMA_OPTIMIZATION_FORCE_END _Pragma ("GCC pop_options")
#elif defined (__ICCARM__)
#define PRAGMA_OPTIMIZATION_FORCE_START _Pragma ("optimize=high z")
#define PRAGMA_OPTIMIZATION_FORCE_END
#endif
void app_util_critical_region_enter (uint8_t *p_nested);
void app_util_critical_region_exit (uint8_t nested);
/**@brief Macro for entering a critical region.
*
* @note Due to implementation details, there must exist one and only one call to
* CRITICAL_REGION_EXIT() for each call to CRITICAL_REGION_ENTER(), and they must be located
* in the same scope.
*/
#ifdef SOFTDEVICE_PRESENT
#define CRITICAL_REGION_ENTER() \
{ \
uint8_t __CR_NESTED = 0; \
app_util_critical_region_enter(&__CR_NESTED);
#else
#define CRITICAL_REGION_ENTER() app_util_critical_region_enter(NULL)
#endif
/**@brief Macro for leaving a critical region.
*
* @note Due to implementation details, there must exist one and only one call to
* CRITICAL_REGION_EXIT() for each call to CRITICAL_REGION_ENTER(), and they must be located
* in the same scope.
*/
#ifdef SOFTDEVICE_PRESENT
#define CRITICAL_REGION_EXIT() \
app_util_critical_region_exit(__CR_NESTED); \
}
#else
#define CRITICAL_REGION_EXIT() app_util_critical_region_exit(0)
#endif
/* Workaround for Keil 4 */
#ifndef IPSR_ISR_Msk
#define IPSR_ISR_Msk (0x1FFUL /*<< IPSR_ISR_Pos*/) /*!< IPSR: ISR Mask */
#endif
/**@brief Macro to enable anonymous unions from a certain point in the code.
*/
#if defined(__CC_ARM)
#define ANON_UNIONS_ENABLE _Pragma("push") \
_Pragma("anon_unions") \
struct semicolon_swallower
#elif defined(__ICCARM__)
#define ANON_UNIONS_ENABLE _Pragma("language=extended") \
struct semicolon_swallower
#else
#define ANON_UNIONS_ENABLE struct semicolon_swallower
// No action will be taken.
// For GCC anonymous unions are enabled by default.
#endif
/**@brief Macro to disable anonymous unions from a certain point in the code.
* @note Call only after first calling @ref ANON_UNIONS_ENABLE.
*/
#if defined(__CC_ARM)
#define ANON_UNIONS_DISABLE _Pragma("pop") \
struct semicolon_swallower
#elif defined(__ICCARM__)
#define ANON_UNIONS_DISABLE struct semicolon_swallower
// for IAR leave anonymous unions enabled
#else
#define ANON_UNIONS_DISABLE struct semicolon_swallower
// No action will be taken.
// For GCC anonymous unions are enabled by default.
#endif
/**@brief Macro for adding pragma directive only for GCC.
*/
#ifdef __GNUC__
#define GCC_PRAGMA(v) _Pragma(v)
#else
#define GCC_PRAGMA(v)
#endif
/* Workaround for Keil 4 */
#ifndef CONTROL_nPRIV_Msk
#define CONTROL_nPRIV_Msk (1UL /*<< CONTROL_nPRIV_Pos*/) /*!< CONTROL: nPRIV Mask */
#endif
/**@brief Function for finding the current interrupt level.
*
* @return Current interrupt level.
* @retval APP_IRQ_PRIORITY_HIGH We are running in Application High interrupt level.
* @retval APP_IRQ_PRIORITY_LOW We are running in Application Low interrupt level.
* @retval APP_IRQ_PRIORITY_THREAD We are running in Thread Mode.
*/
uint8_t current_int_priority_get(void);
/**@brief Function for finding out the current privilege level.
*
* @return Current privilege level.
* @retval APP_LEVEL_UNPRIVILEGED We are running in unprivileged level.
* @retval APP_LEVEL_PRIVILEGED We are running in privileged level.
*/
uint8_t privilege_level_get(void);
#ifdef __cplusplus
}
#endif
#endif // APP_UTIL_PLATFORM_H__
/** @} */

View File

@ -0,0 +1,215 @@
/**
* Copyright (c) 2008 - 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
* @brief Common defines and macros for firmware developed by Nordic Semiconductor.
*/
#ifndef NORDIC_COMMON_H__
#define NORDIC_COMMON_H__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Check if selected module is enabled
*
* This is save function for driver enable checking.
* Correct from Lint point of view (not using default of undefined value).
*
* Usage:
* @code
#if NRF_MODULE_ENABLED(UART)
...
#endif
* @endcode
*
* @param module The module name.
*
* @retval 1 The macro <module>_ENABLE is defined and is non-zero.
* @retval 0 The macro <module>_ENABLE is not defined or it equals zero.
*
* @note
* This macro intentionally does not implement second expansion level.
* The name of the module to be checked has to be given directly as a parameter.
* And given parameter would be connected with @c _ENABLED postfix directly
* without evaluating its value.
*/
//lint -emacro(491,NRF_MODULE_ENABLED) // Suppers warning 491 "non-standard use of 'defined' preprocessor operator"
#ifdef NRF_MODULE_ENABLE_ALL
#warning "Do not use NRF_MODULE_ENABLE_ALL for real builds."
#define NRF_MODULE_ENABLED(module) 1
#else
#define NRF_MODULE_ENABLED(module) \
((defined(module ## _ENABLED) && (module ## _ENABLED)) ? 1 : 0)
#endif
/** The upper 8 bits of a 32 bit value */
//lint -emacro(572,MSB_32) // Suppress warning 572 "Excessive shift value"
#define MSB_32(a) (((a) & 0xFF000000) >> 24)
/** The lower 8 bits (of a 32 bit value) */
#define LSB_32(a) ((a) & 0x000000FF)
/** The upper 8 bits of a 16 bit value */
//lint -emacro(572,MSB_16) // Suppress warning 572 "Excessive shift value"
#define MSB_16(a) (((a) & 0xFF00) >> 8)
/** The lower 8 bits (of a 16 bit value) */
#define LSB_16(a) ((a) & 0x00FF)
/** Leaves the minimum of the two 32-bit arguments */
/*lint -emacro(506, MIN) */ /* Suppress "Constant value Boolean */
#define MIN(a, b) ((a) < (b) ? (a) : (b))
/** Leaves the maximum of the two 32-bit arguments */
/*lint -emacro(506, MAX) */ /* Suppress "Constant value Boolean */
#define MAX(a, b) ((a) < (b) ? (b) : (a))
/**@brief Concatenates two parameters.
*
* It realizes two level expansion to make it sure that all the parameters
* are actually expanded before gluing them together.
*
* @param p1 First parameter to concatenating
* @param p2 Second parameter to concatenating
*
* @return Two parameters glued together.
* They have to create correct C mnemonic in other case
* preprocessor error would be generated.
*
* @sa CONCAT_3
*/
#define CONCAT_2(p1, p2) CONCAT_2_(p1, p2)
/** Auxiliary macro used by @ref CONCAT_2 */
#define CONCAT_2_(p1, p2) p1##p2
/**@brief Concatenates three parameters.
*
* It realizes two level expansion to make it sure that all the parameters
* are actually expanded before gluing them together.
*
* @param p1 First parameter to concatenating
* @param p2 Second parameter to concatenating
* @param p3 Third parameter to concatenating
*
* @return Three parameters glued together.
* They have to create correct C mnemonic in other case
* preprocessor error would be generated.
*
* @sa CONCAT_2
*/
#define CONCAT_3(p1, p2, p3) CONCAT_3_(p1, p2, p3)
/** Auxiliary macro used by @ref CONCAT_3 */
#define CONCAT_3_(p1, p2, p3) p1##p2##p3
#define STRINGIFY_(val) #val
/** Converts a macro argument into a character constant.
*/
#define STRINGIFY(val) STRINGIFY_(val)
/** Counts number of elements inside the array
*/
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
/**@brief Set a bit in the uint32 word.
*
* @param[in] W Word whose bit is being set.
* @param[in] B Bit number in the word to be set.
*/
#define SET_BIT(W, B) ((W) |= (uint32_t)(1U << (B)))
/**@brief Clears a bit in the uint32 word.
*
* @param[in] W Word whose bit is to be cleared.
* @param[in] B Bit number in the word to be cleared.
*/
#define CLR_BIT(W, B) ((W) &= (~(uint32_t)(1U << (B))))
/**@brief Checks if a bit is set.
*
* @param[in] W Word whose bit is to be checked.
* @param[in] B Bit number in the word to be checked.
*
* @retval 1 if bit is set.
* @retval 0 if bit is not set.
*/
#define IS_SET(W, B) (((W) >> (B)) & 1)
#define BIT_0 0x01 /**< The value of bit 0 */
#define BIT_1 0x02 /**< The value of bit 1 */
#define BIT_2 0x04 /**< The value of bit 2 */
#define BIT_3 0x08 /**< The value of bit 3 */
#define BIT_4 0x10 /**< The value of bit 4 */
#define BIT_5 0x20 /**< The value of bit 5 */
#define BIT_6 0x40 /**< The value of bit 6 */
#define BIT_7 0x80 /**< The value of bit 7 */
#define BIT_8 0x0100 /**< The value of bit 8 */
#define BIT_9 0x0200 /**< The value of bit 9 */
#define BIT_10 0x0400 /**< The value of bit 10 */
#define BIT_11 0x0800 /**< The value of bit 11 */
#define BIT_12 0x1000 /**< The value of bit 12 */
#define BIT_13 0x2000 /**< The value of bit 13 */
#define BIT_14 0x4000 /**< The value of bit 14 */
#define BIT_15 0x8000 /**< The value of bit 15 */
#define BIT_16 0x00010000 /**< The value of bit 16 */
#define BIT_17 0x00020000 /**< The value of bit 17 */
#define BIT_18 0x00040000 /**< The value of bit 18 */
#define BIT_19 0x00080000 /**< The value of bit 19 */
#define BIT_20 0x00100000 /**< The value of bit 20 */
#define BIT_21 0x00200000 /**< The value of bit 21 */
#define BIT_22 0x00400000 /**< The value of bit 22 */
#define BIT_23 0x00800000 /**< The value of bit 23 */
#define BIT_24 0x01000000 /**< The value of bit 24 */
#define BIT_25 0x02000000 /**< The value of bit 25 */
#define BIT_26 0x04000000 /**< The value of bit 26 */
#define BIT_27 0x08000000 /**< The value of bit 27 */
#define BIT_28 0x10000000 /**< The value of bit 28 */
#define BIT_29 0x20000000 /**< The value of bit 29 */
#define BIT_30 0x40000000 /**< The value of bit 30 */
#define BIT_31 0x80000000 /**< The value of bit 31 */
#define UNUSED_VARIABLE(X) ((void)(X))
#define UNUSED_PARAMETER(X) UNUSED_VARIABLE(X)
#define UNUSED_RETURN_VALUE(X) UNUSED_VARIABLE(X)
#ifdef __cplusplus
}
#endif
#endif // NORDIC_COMMON_H__

View File

@ -0,0 +1,54 @@
/**
* Copyright (c) 2006 - 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_assert.h"
#include "app_error.h"
#include "nordic_common.h"
__WEAK void assert_nrf_callback(uint16_t line_num, const uint8_t * file_name)
{
assert_info_t assert_info =
{
.line_num = line_num,
.p_file_name = file_name,
};
app_error_fault_handler(NRF_FAULT_ID_SDK_ASSERT, 0, (uint32_t)(&assert_info));
UNUSED_VARIABLE(assert_info);
}

View File

@ -0,0 +1,122 @@
/**
* Copyright (c) 2006 - 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
* @brief Utilities for verifying program logic
*/
#ifndef NRF_ASSERT_H_
#define NRF_ASSERT_H_
#include <stdint.h>
#include "nrf.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Function for handling assertions.
*
*
* @note
* This function is called when an assertion has triggered.
*
* @note
* This function is deprecated and will be removed in future releases.
* Use app_error_fault_handler instead.
*
*
* @post
* All hardware is put into an idle non-emitting state (in particular the radio is highly
* important to switch off since the radio might be in a state that makes it send
* packets continiously while a typical final infinit ASSERT loop is executing).
*
*
* @param line_num The line number where the assertion is called
* @param file_name Pointer to the file name
*/
//lint -save -esym(14, assert_nrf_callback)
void assert_nrf_callback(uint16_t line_num, const uint8_t *file_name);
//lint -restore
#if (defined(DEBUG_NRF) || defined(DEBUG_NRF_USER))
#define NRF_ASSERT_PRESENT 1
#else
#define NRF_ASSERT_PRESENT 0
#endif
//#if defined(DEBUG_NRF) || defined(DEBUG_NRF_USER)
/*lint -emacro(506, ASSERT) */ /* Suppress "Constant value Boolean */
/*lint -emacro(774, ASSERT) */ /* Suppress "Boolean within 'if' always evaluates to True" */ \
/** @brief Function for checking intended for production code.
*
* Check passes if "expr" evaluates to true. */
#ifdef _lint
#define ASSERT(expr) \
if (expr) \
{ \
} \
else \
{ \
while (1); \
}
#else //_lint
#define ASSERT(expr) \
if (NRF_ASSERT_PRESENT) \
{ \
if (expr) \
{ \
} \
else \
{ \
assert_nrf_callback((uint16_t)__LINE__, (uint8_t *)__FILE__); \
} \
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* NRF_ASSERT_H_ */

View File

@ -0,0 +1,147 @@
/**
* Copyright (c) 2006 - 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 NRF_BITMASK_H
#define NRF_BITMASK_H
#include "compiler_abstraction.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define BITMASK_BYTE_GET(abs_bit) ((abs_bit)/8)
#define BITMASK_RELBIT_GET(abs_bit) ((abs_bit) & 0x00000007)
/**
* Function for checking if bit in the multi-byte bit mask is set.
*
* @param bit Bit index.
* @param p_mask A pointer to mask with bit fields.
*
* @return 0 if bit is not set, positive value otherwise.
*/
__STATIC_INLINE uint32_t nrf_bitmask_bit_is_set(uint32_t bit, void const * p_mask)
{
uint8_t const * p_mask8 = (uint8_t const *)p_mask;
uint32_t byte_idx = BITMASK_BYTE_GET(bit);
bit = BITMASK_RELBIT_GET(bit);
return (1 << bit) & p_mask8[byte_idx];
}
/**
* Function for setting a bit in the multi-byte bit mask.
*
* @param bit Bit index.
* @param p_mask A pointer to mask with bit fields.
*/
__STATIC_INLINE void nrf_bitmask_bit_set(uint32_t bit, void * p_mask)
{
uint8_t * p_mask8 = (uint8_t *)p_mask;
uint32_t byte_idx = BITMASK_BYTE_GET(bit);
bit = BITMASK_RELBIT_GET(bit);
p_mask8[byte_idx] |= (1 << bit);
}
/**
* Function for clearing a bit in the multi-byte bit mask.
*
* @param bit Bit index.
* @param p_mask A pointer to mask with bit fields.
*/
__STATIC_INLINE void nrf_bitmask_bit_clear(uint32_t bit, void * p_mask)
{
uint8_t * p_mask8 = (uint8_t *)p_mask;
uint32_t byte_idx = BITMASK_BYTE_GET(bit);
bit = BITMASK_RELBIT_GET(bit);
p_mask8[byte_idx] &= ~(1 << bit);
}
/**
* Function for performing bitwise OR operation on two multi-byte bit masks.
*
* @param p_mask1 A pointer to the first bit mask.
* @param p_mask2 A pointer to the second bit mask.
* @param p_mask_out A pointer to the output bit mask.
* @param length Length of output mask in bytes.
*/
__STATIC_INLINE void nrf_bitmask_masks_or(void const * p_mask1,
void const * p_mask2,
void * p_out_mask,
uint32_t length)
{
uint8_t const * p_mask8_1 = (uint8_t const *)p_mask1;
uint8_t const * p_mask8_2 = (uint8_t const *)p_mask2;
uint8_t * p_mask8_out = (uint8_t *)p_out_mask;
uint32_t i;
for (i = 0; i < length; i++)
{
p_mask8_out[i] = p_mask8_1[i] | p_mask8_2[i];
}
}
/**
* Function for performing bitwise AND operation on two multi-byte bit masks.
*
* @param p_mask1 A pointer to the first bit mask.
* @param p_mask2 A pointer to the second bit mask.
* @param p_mask_out A pointer to the output bit mask.
* @param length Length of output mask in bytes.
*/
__STATIC_INLINE void nrf_bitmask_masks_and(void const * p_mask1,
void const * p_mask2,
void * p_out_mask,
uint32_t length)
{
uint8_t const * p_mask8_1 = (uint8_t const *)p_mask1;
uint8_t const * p_mask8_2 = (uint8_t const *)p_mask2;
uint8_t * p_mask8_out = (uint8_t *)p_out_mask;
uint32_t i;
for (i = 0; i < length; i++)
{
p_mask8_out[i] = p_mask8_1[i] & p_mask8_2[i];
}
}
#ifdef __cplusplus
}
#endif
#endif //NRF_BITMASK_H

View File

@ -0,0 +1,85 @@
/**
* 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 sdk_alloca.h
*
* @brief Defines alloca() function.
*
* @details This file defines alloca() function. This can be done directly or by including system
* header files. Not all platforms support alloca(). In this case no error will be shown, but
* SDK_ALLOCA_DEFINED will be set to 0.
*/
#ifndef SDK_ALLOCA_H__
#define SDK_ALLOCA_H__
#if defined(__SDK_DOXYGEN__)
/** @brief Set to one it alloca() function is available on this platform and it is correctly defined
* by this header file.
*/
#define SDK_ALLOCA_DEFINED 1
#elif defined(__GNUC__)
#if defined(__SES_ARM)
// SES does not have definition of alloca(), but it have working GCC's __builtin_alloca().
#if !defined(alloca)
#define alloca(size) __builtin_alloca((size))
#endif
#else
// alloca() can be defined in <malloc.h> on some platforms, but if not then try standard <alloca.h> header file.
#include <malloc.h>
#if !defined(alloca)
#include <alloca.h>
#endif
#endif
#define SDK_ALLOCA_DEFINED 1
#elif defined(__IAR_SYSTEMS_ICC__)
// IAR does not support alloca() function.
#define SDK_ALLOCA_DEFINED 0
#else
// All other supported compilers have alloca() definition in <alloca.h> header file.
#include <alloca.h>
#define SDK_ALLOCA_DEFINED 1
#endif
/*lint -"d__builtin_alloca=(void*)" */
#endif // NRF_ALLOCA_H__

View File

@ -0,0 +1,77 @@
/**
* Copyright (c) 2013 - 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.
*
*/
/** @cond */
/**@file
*
* @ingroup experimental_api
* @defgroup sdk_common SDK Common Header
* @brief All common headers needed for SDK examples will be included here so that application
* developer does not have to include headers on him/herself.
* @{
*/
#ifndef SDK_COMMON_H__
#define SDK_COMMON_H__
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "sdk_config.h"
#include "nordic_common.h"
#include "compiler_abstraction.h"
#include "sdk_os.h"
#include "sdk_errors.h"
#include "app_util.h"
#include "sdk_macros.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @} */
/** @endcond */
#ifdef __cplusplus
}
#endif
#endif // SDK_COMMON_H__

View File

@ -0,0 +1,167 @@
/**
* Copyright (c) 2013 - 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_error SDK Error codes
* @{
* @ingroup app_common
* @{
* @details Error codes are 32-bit unsigned integers with the most significant 16-bit reserved for
* identifying the module where the error occurred while the least least significant LSB
* are used to provide the cause or nature of error. Each module is assigned a 16-bit
* unsigned integer. Which it will use to identify all errors that occurred in it. 16-bit
* LSB range is with module id as the MSB in the 32-bit error code is reserved for the
* module. As an example, if 0x8800 identifies a certain SDK module, all values from
* 0x88000000 - 0x8800FFFF are reserved for this module.
* It should be noted that common error reasons have been assigned values to make it
* possible to decode error reason easily. As an example, lets module uninitialized has
* been assigned an error code 0x000A0. Then, if application encounters an error code
* 0xZZZZ00A0, it knows that it accessing a certain module without initializing it.
* Apart from this, each module is allowed to define error codes that are not covered by
* the common ones, however, these values are defined in a range that does not conflict
* with common error values. For module, specific error however, it is possible that the
* same error value is used by two different modules to indicated errors of very different
* nature. If error is already defined by the NRF common error codes, these are reused.
* A range is reserved for application as well, it can use this range for defining
* application specific errors.
*
* @note Success code, NRF_SUCCESS, does not include any module identifier.
*/
#ifndef SDK_ERRORS_H__
#define SDK_ERRORS_H__
#include <stdint.h>
#include "nrf_error.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup sdk_err_base Base defined for SDK Modules
* @{
*/
#define NRF_ERROR_SDK_ERROR_BASE (NRF_ERROR_BASE_NUM + 0x8000) /**< Base value defined for SDK module identifiers. */
#define NRF_ERROR_SDK_COMMON_ERROR_BASE (NRF_ERROR_BASE_NUM + 0x0080) /**< Base error value to be used for SDK error values. */
/** @} */
/**
* @defgroup sdk_module_codes Codes reserved as identification for module where the error occurred.
* @{
*/
#define NRF_ERROR_MEMORY_MANAGER_ERR_BASE (0x8100) /**< Base address for Memory Manager related errors. */
#define NRF_ERROR_PERIPH_DRIVERS_ERR_BASE (0x8200) /**< Base address for Peripheral drivers related errors. */
#define NRF_ERROR_GAZELLE_ERR_BASE (0x8300) /**< Base address for Gazelle related errors. */
#define NRF_ERROR_BLE_IPSP_ERR_BASE (0x8400) /**< Base address for BLE IPSP related errors. */
#define NRF_ERROR_CRYPTO_ERR_BASE (0x8500) /**< Base address for crypto related errors. */
/** @} */
/**
* @defgroup sdk_iot_errors Codes reserved as identification for IoT errors.
* @{
*/
#define NRF_ERROR_IOT_ERR_BASE_START (0xA000)
#define NRF_ERROR_IOT_ERR_BASE_STOP (0xAFFF)
/** @} */
/**
* @defgroup sdk_common_errors Codes reserved as identification for common errors.
* @{
*/
#define NRF_ERROR_MODULE_NOT_INITIALIZED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0000) ///< Module not initialized
#define NRF_ERROR_MUTEX_INIT_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0001) ///< Mutex initialization failed
#define NRF_ERROR_MUTEX_LOCK_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0002) ///< Mutex lock failed
#define NRF_ERROR_MUTEX_UNLOCK_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0003) ///< Mutex unlock failed
#define NRF_ERROR_MUTEX_COND_INIT_FAILED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0004) ///< Mutex conditional initialization failed
#define NRF_ERROR_MODULE_ALREADY_INITIALIZED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0005) ///< Module already initialized
#define NRF_ERROR_STORAGE_FULL (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0006) ///< Storage full
#define NRF_ERROR_API_NOT_IMPLEMENTED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0010) ///< API not implemented
#define NRF_ERROR_FEATURE_NOT_ENABLED (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0011) ///< Feature not enabled
#define NRF_ERROR_IO_PENDING (NRF_ERROR_SDK_COMMON_ERROR_BASE + 0x0012) ///< Input/Output pending
/** @} */
/**
* @defgroup drv_specific_errors Error / status codes specific to drivers.
* @{
*/
#define NRF_ERROR_DRV_TWI_ERR_OVERRUN (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0000)
#define NRF_ERROR_DRV_TWI_ERR_ANACK (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0001)
#define NRF_ERROR_DRV_TWI_ERR_DNACK (NRF_ERROR_PERIPH_DRIVERS_ERR_BASE + 0x0002)
/** @} */
/**
* @defgroup ble_ipsp_errors IPSP codes
* @brief Error and status codes specific to IPSP.
* @{
*/
#define NRF_ERROR_BLE_IPSP_RX_PKT_TRUNCATED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0000)
#define NRF_ERROR_BLE_IPSP_CHANNEL_ALREADY_EXISTS (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0001)
#define NRF_ERROR_BLE_IPSP_LINK_DISCONNECTED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0002)
#define NRF_ERROR_BLE_IPSP_PEER_REJECTED (NRF_ERROR_BLE_IPSP_ERR_BASE + 0x0003)
/* @} */
/**
* @brief API Result.
*
* @details Indicates success or failure of an API procedure. In case of failure, a comprehensive
* error code indicating cause or reason for failure is provided.
*
* Though called an API result, it could used in Asynchronous notifications callback along
* with asynchronous callback as event result. This mechanism is employed when an event
* marks the end of procedure initiated using API. API result, in this case, will only be
* an indicative of whether the procedure has been requested successfully.
*/
typedef uint32_t ret_code_t;
/** @} */
/** @} */
#ifdef __cplusplus
}
#endif
#endif // SDK_ERRORS_H__

View File

@ -0,0 +1,215 @@
/**
* Copyright (c) 2013 - 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_common_macros SDK Common Header
* @ingroup app_common
* @brief Macros for parameter checking and similar tasks
* @{
*/
#ifndef SDK_MACROS_H__
#define SDK_MACROS_H__
#include "nrf_assert.h"
#ifdef __cplusplus
extern "C" {
#endif
/**@brief Macro for parameter checking.
*
* If @p _cond evaluates to true, does nothing. Otherwise,
* if @p _module ## _PARAM_CHECK_DISABLED is @e not set (default), prints an error message
* if @p _printfn is provided, and returns from the calling function context with code @p _err.
* If @p _module ## _PARAM_CHECK_DISABLED is set, behaves like the ASSERT macro.
*
* Parameter checking implemented using this macro can be optionally turned off for release code.
* Only disable runtime parameter checks if size if a major concern.
*
* @param _module The module name.
* @param _cond The condition to be evaluated.
* @param _err The error to be returned.
* @param _printfn A printf-compatible function used to log the error.
* Leave empty if no logging is needed.
*
* @hideinitializer
*/
/*lint -esym(666, NRF_PARAM_CHECK*) : Expression with side effects passed to macro */
#define NRF_PARAM_CHECK(_module, _cond, _err, _printfn) \
do \
{ \
if ((_cond)) \
{ \
/* Do nothing. */ \
} \
else if (!(_module ## _PARAM_CHECK_DISABLED)) \
{ \
_printfn("%s check failed in %s() with value 0x%x.", #_cond, __func__, _err); \
return (_err); \
} \
else \
{ \
ASSERT((_cond)); \
} \
} while (0);
/**@brief Macro for verifying statement to be true. It will cause the exterior function to return
* err_code if the statement is not true.
*
* @param[in] statement Statement to test.
* @param[in] err_code Error value to return if test was invalid.
*
* @retval nothing, but will cause the exterior function to return @p err_code if @p statement
* is false.
*/
#define VERIFY_TRUE(statement, err_code) \
do \
{ \
if (!(statement)) \
{ \
return err_code; \
} \
} while (0)
/**@brief Macro for verifying statement to be true. It will cause the exterior function to return
* if the statement is not true.
*
* @param[in] statement Statement to test.
*/
#define VERIFY_TRUE_VOID(statement) VERIFY_TRUE((statement), )
/**@brief Macro for verifying statement to be false. It will cause the exterior function to return
* err_code if the statement is not false.
*
* @param[in] statement Statement to test.
* @param[in] err_code Error value to return if test was invalid.
*
* @retval nothing, but will cause the exterior function to return @p err_code if @p statement
* is true.
*/
#define VERIFY_FALSE(statement, err_code) \
do \
{ \
if ((statement)) \
{ \
return err_code; \
} \
} while (0)
/**@brief Macro for verifying statement to be false. It will cause the exterior function to return
* if the statement is not false.
*
* @param[in] statement Statement to test.
*/
#define VERIFY_FALSE_VOID(statement) VERIFY_FALSE((statement), )
/**@brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the exterior
* function to return error code of statement if it is not @ref NRF_SUCCESS.
*
* @param[in] statement Statement to check against NRF_SUCCESS.
*/
#define VERIFY_SUCCESS(statement) \
do \
{ \
uint32_t _err_code = (uint32_t) (statement); \
if (_err_code != NRF_SUCCESS) \
{ \
return _err_code; \
} \
} while(0)
/**@brief Macro for verifying that a function returned NRF_SUCCESS. It will cause the exterior
* function to return if the err_code is not @ref NRF_SUCCESS.
*
* @param[in] err_code The error code to check.
*/
#define VERIFY_SUCCESS_VOID(err_code) VERIFY_TRUE_VOID((err_code) == NRF_SUCCESS)
/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to
* return @ref NRF_ERROR_INVALID_STATE if not.
*
* @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED
* should be true if the module is initialized, false if not.
*/
#define VERIFY_MODULE_INITIALIZED() VERIFY_TRUE((MODULE_INITIALIZED), NRF_ERROR_INVALID_STATE)
/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to
* return if not.
*
* @note MODULE_INITIALIZED must be defined in each module using this macro. MODULE_INITIALIZED
* should be true if the module is initialized, false if not.
*/
#define VERIFY_MODULE_INITIALIZED_VOID() VERIFY_TRUE_VOID((MODULE_INITIALIZED))
/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to
* return if not.
*
* @param[in] param The variable to check if is NULL.
*/
#define VERIFY_PARAM_NOT_NULL(param) VERIFY_FALSE(((param) == NULL), NRF_ERROR_NULL)
/**@brief Macro for verifying that the module is initialized. It will cause the exterior function to
* return if not.
*
* @param[in] param The variable to check if is NULL.
*/
#define VERIFY_PARAM_NOT_NULL_VOID(param) VERIFY_FALSE_VOID(((param) == NULL))
/** @} */
#ifdef __cplusplus
}
#endif
#endif // SDK_MACROS_H__

View File

@ -0,0 +1,220 @@
/**
* 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.
*
*/
#include "sdk_mapped_flags.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "compiler_abstraction.h"
// Test whether the flag collection type is large enough to hold all the flags. If this fails,
// reduce SDK_MAPPED_FLAGS_N_KEYS or increase the size of sdk_mapped_flags_t.
STATIC_ASSERT((sizeof(sdk_mapped_flags_t) * SDK_MAPPED_FLAGS_N_KEYS_PER_BYTE) >= SDK_MAPPED_FLAGS_N_KEYS);
/**@brief Function for setting the state of a flag to true.
*
* @note This function does not check whether the index is valid.
*
* @param[in] p_flags The collection of flags to modify.
* @param[in] index The index of the flag to modify.
*/
static __INLINE void sdk_mapped_flags_set_by_index(sdk_mapped_flags_t * p_flags, uint16_t index)
{
*p_flags |= (1U << index);
}
/**@brief Function for setting the state of a flag to false.
*
* @note This function does not check whether the index is valid.
*
* @param[in] p_flags The collection of flags to modify.
* @param[in] index The index of the flag to modify.
*/
static __INLINE void sdk_mapped_flags_clear_by_index(sdk_mapped_flags_t * p_flags, uint16_t index)
{
*p_flags &= ~(1U << index);
}
/**@brief Function for getting the state of a flag.
*
* @note This function does not check whether the index is valid.
*
* @param[in] p_flags The collection of flags to read.
* @param[in] index The index of the flag to get.
*/
static __INLINE bool sdk_mapped_flags_get_by_index(sdk_mapped_flags_t flags, uint16_t index)
{
return ((flags & (1 << index)) != 0);
}
uint16_t sdk_mapped_flags_first_key_index_get(sdk_mapped_flags_t flags)
{
for (uint16_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++)
{
if (sdk_mapped_flags_get_by_index(flags, i))
{
return i;
}
}
return SDK_MAPPED_FLAGS_INVALID_INDEX;
}
void sdk_mapped_flags_update_by_key(uint16_t * p_keys,
sdk_mapped_flags_t * p_flags,
uint16_t key,
bool value)
{
sdk_mapped_flags_bulk_update_by_key(p_keys, p_flags, 1, key, value);
}
void sdk_mapped_flags_bulk_update_by_key(uint16_t * p_keys,
sdk_mapped_flags_t * p_flags,
uint32_t n_flag_collections,
uint16_t key,
bool value)
{
if ((p_keys != NULL) && (p_flags != NULL) && (n_flag_collections > 0))
{
for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++)
{
if (p_keys[i] == key)
{
for (uint32_t j = 0; j < n_flag_collections; j++)
{
if (value)
{
sdk_mapped_flags_set_by_index(&p_flags[j], i);
}
else
{
sdk_mapped_flags_clear_by_index(&p_flags[j], i);
}
}
return;
}
}
}
}
bool sdk_mapped_flags_get_by_key_w_idx(uint16_t * p_keys,
sdk_mapped_flags_t flags,
uint16_t key,
uint8_t * p_index)
{
if (p_keys != NULL)
{
for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++)
{
if (p_keys[i] == key)
{
if (p_index != NULL)
{
*p_index = i;
}
return sdk_mapped_flags_get_by_index(flags, i);
}
}
}
if (p_index != NULL)
{
*p_index = SDK_MAPPED_FLAGS_N_KEYS;
}
return false;
}
bool sdk_mapped_flags_get_by_key(uint16_t * p_keys, sdk_mapped_flags_t flags, uint16_t key)
{
if (p_keys != NULL)
{
for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++)
{
if (p_keys[i] == key)
{
return sdk_mapped_flags_get_by_index(flags, i);
}
}
}
return false;
}
sdk_mapped_flags_key_list_t sdk_mapped_flags_key_list_get(uint16_t * p_keys,
sdk_mapped_flags_t flags)
{
sdk_mapped_flags_key_list_t key_list;
key_list.len = 0;
if (p_keys != NULL)
{
for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++)
{
if (sdk_mapped_flags_get_by_index(flags, i))
{
key_list.flag_keys[key_list.len++] = p_keys[i];
}
}
}
return key_list;
}
uint32_t sdk_mapped_flags_n_flags_set(sdk_mapped_flags_t flags)
{
uint32_t n_flags_set = 0;
for (uint32_t i = 0; i < SDK_MAPPED_FLAGS_N_KEYS; i++)
{
if (sdk_mapped_flags_get_by_index(flags, i))
{
n_flags_set += 1;
}
}
return n_flags_set;
}

View File

@ -0,0 +1,199 @@
/**
* 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 SDK_MAPPED_FLAGS_H__
#define SDK_MAPPED_FLAGS_H__
#include <stdint.h>
#include <stdbool.h>
#include "app_util.h"
#include "compiler_abstraction.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file
* @defgroup sdk_mapped_flags Mapped flags
* @ingroup app_common
* @{
* @brief Module for writing and reading flags that are associated
* with keys.
*
* @details The flags are represented as bits in a bitmap called a <i>flag collection</i>. The keys
* are uint16_t. Each flag collection contains all flags of the same type, one flag for
* each key.
*
* The mapped flags module does not keep the flag states, nor the list of keys. These are
* provided in the API calls. A key's index in the key list determines which bit in the
* flag collection is associated with it. This module does not ever edit the key list, and
* does not edit flags except in function calls that take the flag collection as a pointer.
*
*/
#define SDK_MAPPED_FLAGS_N_KEYS 32 /**< The number of keys to keep flags for. This is also the number of flags in a flag collection. If changing this value, you might also need change the width of the sdk_mapped_flags_t type. */
#define SDK_MAPPED_FLAGS_N_KEYS_PER_BYTE 8 /**< The number of flags that fit in one byte. */
#define SDK_MAPPED_FLAGS_INVALID_INDEX 0xFFFF /**< A flag index guaranteed to be invalid. */
typedef uint32_t sdk_mapped_flags_t; /**< The bitmap to hold flags. Each flag is one bit, and each bit represents the flag state associated with one key. */
/**@brief Type used to present a subset of the registered keys.
*/
typedef struct
{
uint32_t len; /**< The length of the list. */
uint16_t flag_keys[SDK_MAPPED_FLAGS_N_KEYS]; /**< The list of keys. */
} sdk_mapped_flags_key_list_t;
/**@brief Function for getting the first index at which the flag is true in the provided
* collection.
*
* @param[in] flags The flag collection to search for a flag set to true.
*
* @return The first index that has its flag set to true. If none were found, the
* function returns @ref SDK_MAPPED_FLAGS_INVALID_INDEX.
*/
uint16_t sdk_mapped_flags_first_key_index_get(sdk_mapped_flags_t flags);
/**@brief Function for updating the state of a flag.
*
* @param[in] p_keys The list of associated keys (assumed to have a length of
* @ref SDK_MAPPED_FLAGS_N_KEYS).
* @param[out] p_flags The flag collection to modify.
* @param[in] key The key to modify the flag of.
* @param[in] value The state to set the flag to.
*/
void sdk_mapped_flags_update_by_key(uint16_t * p_keys,
sdk_mapped_flags_t * p_flags,
uint16_t key,
bool value);
/**@brief Function for updating the state of the same flag in multiple flag collections.
*
* @details The key and value are the same for all flag collections in the p_flags array.
*
* @param[in] p_keys The list of associated keys (assumed to have a length of
* @ref SDK_MAPPED_FLAGS_N_KEYS).
* @param[out] p_flags The flag collections to modify.
* @param[out] n_flag_collections The number of flag collections in p_flags.
* @param[in] key The key to modify the flag of.
* @param[in] value The state to set the flag to.
*/
void sdk_mapped_flags_bulk_update_by_key(uint16_t * p_keys,
sdk_mapped_flags_t * p_flags,
uint32_t n_flag_collections,
uint16_t key,
bool value);
/**@brief Function for getting the state of a specific flag.
*
* @param[in] p_keys The list of associated keys (assumed to have a length of
* @ref SDK_MAPPED_FLAGS_N_KEYS).
* @param[in] flags The flag collection to read from.
* @param[in] key The key to get the flag for.
*
* @return The state of the flag.
*/
bool sdk_mapped_flags_get_by_key(uint16_t * p_keys, sdk_mapped_flags_t flags, uint16_t key);
/**@brief Function for getting the state of a specific flag.
*
* @param[in] p_keys The list of associated keys (assumed to have a length of
* @ref SDK_MAPPED_FLAGS_N_KEYS).
* @param[in] flags The flag collection from which to read.
* @param[in] key The key for which to get the flag.
* @param[out] p_index If not NULL, the index of the key.
*
* @return The state of the flag.
*/
bool sdk_mapped_flags_get_by_key_w_idx(uint16_t * p_keys,
sdk_mapped_flags_t flags,
uint16_t key,
uint8_t * p_index);
/**@brief Function for getting a list of all keys that have a specific flag set to true.
*
* @param[in] p_keys The list of associated keys (assumed to have a length of
* @ref SDK_MAPPED_FLAGS_N_KEYS).
* @param[in] flags The flag collection to search.
*
* @return The list of keys.
*/
sdk_mapped_flags_key_list_t sdk_mapped_flags_key_list_get(uint16_t * p_keys,
sdk_mapped_flags_t flags);
/**@brief Function for getting the number of keys that have a specific flag set to true.
*
* @param[in] flags The flag collection to search.
*
* @return The number of keys.
*/
uint32_t sdk_mapped_flags_n_flags_set(sdk_mapped_flags_t flags);
/**@brief Function for querying whether any flags in the collection are set.
*
* @param[in] flags The flag collection to query.
*
* @retval true If one or more flags are set to true.
* @retval false Otherwise.
*/
static __INLINE bool sdk_mapped_flags_any_set(sdk_mapped_flags_t flags)
{
return (flags != 0);
}
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* SDK_MAPPED_FLAGS_H__ */

View File

@ -0,0 +1,76 @@
/**
* Copyright (c) 2013 - 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.
*
*/
/** @cond */
/**@file
*
* @defgroup sdk_os SDK OS Abstraction
* @ingroup experimental_api
* @details In order to made SDK modules independent of use of an embedded OS, and permit
* application with varied task architecture, SDK abstracts the OS specific
* elements here in order to make all other modules agnostic to the OS or task
* architecture.
* @{
*/
#ifndef SDK_OS_H__
#define SDK_OS_H__
#ifdef __cplusplus
extern "C" {
#endif
#define SDK_MUTEX_DEFINE(X)
#define SDK_MUTEX_INIT(X)
#define SDK_MUTEX_LOCK(X)
#define SDK_MUTEX_UNLOCK(X)
/**
* @defgroup os_data_type Data types.
*/
/** @} */
/** @endcond */
#ifdef __cplusplus
}
#endif
#endif // SDK_OS_H__

View File

@ -0,0 +1,86 @@
/**
* 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.
*
*/
/** @file
* @brief Definition file for resource usage by SoftDevice, ESB and Gazell.
*/
#ifndef SDK_RESOURCES_H__
#define SDK_RESOURCES_H__
#ifdef __cplusplus
extern "C" {
#endif
#if defined(SOFTDEVICE_PRESENT) || defined (BLE_STACK_SUPPORT_REQD) || defined (ANT_STACK_SUPPORT_REQD)
#include "nrf_sd_def.h"
#else
#define SD_PPI_RESTRICTED 0uL /**< 1 if PPI peripheral is restricted, 0 otherwise. */
#define SD_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by SotfDevice (not available to th spplication). */
#define SD_PPI_GROUPS_USED 0uL /**< PPI groups utilized by SotfDevice (not available to th spplication). */
#define SD_TIMERS_USED 0uL /**< Timers used by SoftDevice. */
#define SD_SWI_USED 0uL /**< Software interrupts used by SoftDevice. */
#endif
#ifdef GAZELL_PRESENT
#include "nrf_gzll_resources.h"
#else
#define GZLL_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by Gazell (not available to th spplication). */
#define GZLL_TIMERS_USED 0uL /**< Timers used by Gazell. */
#define GZLL_SWI_USED 0uL /**< Software interrupts used by Gazell */
#endif
#ifdef ESB_PRESENT
#include "nrf_esb_resources.h"
#else
#define ESB_PPI_CHANNELS_USED 0uL /**< PPI channels utilized by ESB (not available to th spplication). */
#define ESB_TIMERS_USED 0uL /**< Timers used by ESB. */
#define ESB_SWI_USED 0uL /**< Software interrupts used by ESB */
#endif
#define NRF_PPI_CHANNELS_USED (SD_PPI_CHANNELS_USED | GZLL_PPI_CHANNELS_USED | ESB_PPI_CHANNELS_USED)
#define NRF_PPI_GROUPS_USED (SD_PPI_GROUPS_USED)
#define NRF_SWI_USED (SD_SWI_USED | GZLL_SWI_USED | ESB_SWI_USED)
#define NRF_TIMERS_USED (SD_TIMERS_USED | GZLL_TIMERS_USED | ESB_TIMERS_USED)
#ifdef __cplusplus
}
#endif
#endif // SDK_RESOURCES_H__

View File

@ -0,0 +1,297 @@
/**
* 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.
*
*/
#ifndef NRF_DRV_CLOCK_H__
#define NRF_DRV_CLOCK_H__
#include <nrfx_clock.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup nrf_drv_clock Clock driver - legacy layer
* @{
* @ingroup nrf_clock
*
* @brief Layer providing compatibility with the former API.
*/
/**
* @brief Clock events.
*/
typedef enum
{
NRF_DRV_CLOCK_EVT_HFCLK_STARTED, ///< HFCLK has been started.
NRF_DRV_CLOCK_EVT_LFCLK_STARTED, ///< LFCLK has been started.
NRF_DRV_CLOCK_EVT_CAL_DONE, ///< Calibration is done.
NRF_DRV_CLOCK_EVT_CAL_ABORTED, ///< Calibration has been aborted.
} nrf_drv_clock_evt_type_t;
/**
* @brief Clock event handler.
*
* @param[in] event Event.
*/
typedef void (*nrf_drv_clock_event_handler_t)(nrf_drv_clock_evt_type_t event);
// Forward declaration of the nrf_drv_clock_handler_item_t type.
typedef struct nrf_drv_clock_handler_item_s nrf_drv_clock_handler_item_t;
struct nrf_drv_clock_handler_item_s
{
nrf_drv_clock_handler_item_t * p_next; ///< A pointer to the next handler that should be called when the clock is started.
nrf_drv_clock_event_handler_t event_handler; ///< Function to be called when the clock is started.
};
/**
* @brief Function for checking if driver is already initialized
*
* @retval true Driver is initialized
* @retval false Driver is uninitialized
*/
bool nrf_drv_clock_init_check(void);
/**
* @brief Function for initializing the nrf_drv_clock module.
*
* After initialization, the module is in power off state (clocks are not requested).
*
* @retval NRF_SUCCESS If the procedure was successful.
* @retval NRF_ERROR_MODULE_ALREADY_INITIALIZED If the driver was already initialized.
*/
ret_code_t nrf_drv_clock_init(void);
/**
* @brief Function for uninitializing the clock module.
*
*/
void nrf_drv_clock_uninit(void);
/**
* @brief Function for requesting the LFCLK.
*
* The low-frequency clock can be requested by different modules
* or contexts. The driver ensures that the clock will be started only when it is requested
* the first time. If the clock is not ready but it was already started, the handler item that is
* provided as an input parameter is added to the list of handlers that will be notified
* when the clock is started. If the clock is already enabled, user callback is called from the
* current context.
*
* The first request will start the selected LFCLK source. If an event handler is
* provided, it will be called once the LFCLK is started. If the LFCLK was already started at this
* time, the event handler will be called from the context of this function. Additionally,
* the @ref nrf_drv_clock_lfclk_is_running function can be polled to check if the clock has started.
*
* @note When a SoftDevice is enabled, the LFCLK is always running and the driver cannot control it.
*
* @note The handler item provided by the user cannot be an automatic variable.
*
* @param[in] p_handler_item A pointer to the event handler structure.
*/
void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t * p_handler_item);
/**
* @brief Function for releasing the LFCLK.
*
* If there are no more requests, the LFCLK source will be stopped.
*
* @note When a SoftDevice is enabled, the LFCLK is always running.
*/
void nrf_drv_clock_lfclk_release(void);
/**
* @brief Function for checking the LFCLK state.
*
* @retval true If the LFCLK is running.
* @retval false If the LFCLK is not running.
*/
bool nrf_drv_clock_lfclk_is_running(void);
/**
* @brief Function for requesting the high-accuracy source HFCLK.
*
* The high-accuracy source
* can be requested by different modules or contexts. The driver ensures that the high-accuracy
* clock will be started only when it is requested the first time. If the clock is not ready
* but it was already started, the handler item that is provided as an input parameter is added
* to the list of handlers that will be notified when the clock is started.
*
* If an event handler is provided, it will be called once the clock is started. If the clock was already
* started at this time, the event handler will be called from the context of this function. Additionally,
* the @ref nrf_drv_clock_hfclk_is_running function can be polled to check if the clock has started.
*
* @note If a SoftDevice is running, the clock is managed by the SoftDevice and all requests are handled by
* the SoftDevice. This function cannot be called from all interrupt priority levels in that case.
* @note The handler item provided by the user cannot be an automatic variable.
*
* @param[in] p_handler_item A pointer to the event handler structure.
*/
void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item);
/**
* @brief Function for releasing the high-accuracy source HFCLK.
*
* If there are no more requests, the high-accuracy source will be released.
*/
void nrf_drv_clock_hfclk_release(void);
/**
* @brief Function for checking the HFCLK state.
*
* @retval true If the HFCLK is running (for \nRFXX XTAL source).
* @retval false If the HFCLK is not running.
*/
bool nrf_drv_clock_hfclk_is_running(void);
/**
* @brief Function for starting a single calibration process.
*
* This function can also delay the start of calibration by a user-specified value. The delay will use
* a low-power timer that is part of the CLOCK module. @ref nrf_drv_clock_is_calibrating can be called to
* check if calibration is still in progress. If a handler is provided, the user can be notified when
* calibration is completed. The ext calibration can be started from the handler context.
*
* The calibration process consists of three phases:
* - Delay (optional)
* - Requesting the high-accuracy HFCLK
* - Hardware-supported calibration
*
* @param[in] delay Time after which the calibration will be started (in 0.25 s units).
* @param[in] handler NULL or user function to be called when calibration is completed or aborted.
*
* @retval NRF_SUCCESS If the procedure was successful.
* @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator.
* @retval NRF_ERROR_INVALID_STATE If the low-frequency clock is off.
* @retval NRF_ERROR_BUSY If calibration is in progress.
*/
ret_code_t nrf_drv_clock_calibration_start(uint8_t delay, nrf_drv_clock_event_handler_t handler);
/**
* @brief Function for aborting calibration.
*
* This function aborts on-going calibration. If calibration was started, it cannot be stopped. If a handler
* was provided by @ref nrf_drv_clock_calibration_start, this handler will be called once
* aborted calibration is completed. @ref nrf_drv_clock_is_calibrating can also be used to check
* if the system is calibrating.
*
* @retval NRF_SUCCESS If the procedure was successful.
* @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator.
*/
ret_code_t nrf_drv_clock_calibration_abort(void);
/**
* @brief Function for checking if calibration is in progress.
*
* This function indicates that the system is
* in calibration if it is in any of the calibration process phases (see @ref nrf_drv_clock_calibration_start).
*
* @param[out] p_is_calibrating True if calibration is in progress, false if not.
*
* @retval NRF_SUCCESS If the procedure was successful.
* @retval NRF_ERROR_FORBIDDEN If a SoftDevice is present or the selected LFCLK source is not an RC oscillator.
*/
ret_code_t nrf_drv_clock_is_calibrating(bool * p_is_calibrating);
/**@brief Function for returning a requested task address for the clock driver module.
*
* @param[in] task One of the peripheral tasks.
*
* @return Task address.
*/
__STATIC_INLINE uint32_t nrf_drv_clock_ppi_task_addr(nrf_clock_task_t task);
/**@brief Function for returning a requested event address for the clock driver module.
*
* @param[in] event One of the peripheral events.
*
* @return Event address.
*/
__STATIC_INLINE uint32_t nrf_drv_clock_ppi_event_addr(nrf_clock_event_t event);
#ifdef SOFTDEVICE_PRESENT
/**
* @brief Function called by the SoftDevice handler if an @ref NRF_SOC_EVTS event is received from the SoftDevice.
*
* @param[in] evt_id One of NRF_SOC_EVTS values.
*/
void nrf_drv_clock_on_soc_event(uint32_t evt_id);
/**
* @brief Function called by the SoftDevice handler when the SoftDevice has been enabled.
*
* This function is called just after the SoftDevice has been properly enabled.
* Its main purpose is to mark that LFCLK has been requested by SD.
*/
void nrf_drv_clock_on_sd_enable(void);
/**
* @brief Function called by the SoftDevice handler when the SoftDevice has been disabled.
*
* This function is called just after the SoftDevice has been properly disabled.
* It has two purposes:
* 1. Releases the LFCLK from the SD.
* 2. Reinitializes an interrupt after the SD releases POWER_CLOCK_IRQ.
*/
void nrf_drv_clock_on_sd_disable(void);
#endif
/**
*@}
**/
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE uint32_t nrf_drv_clock_ppi_task_addr(nrf_clock_task_t task)
{
return nrf_clock_task_address_get(task);
}
__STATIC_INLINE uint32_t nrf_drv_clock_ppi_event_addr(nrf_clock_event_t event)
{
return nrf_clock_event_address_get(event);
}
#endif //SUPPRESS_INLINE_IMPLEMENTATION
#ifdef __cplusplus
}
#endif
#endif // NRF_DRV_CLOCK_H__

View File

@ -0,0 +1,63 @@
/**
* 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 NRF_DRV_COMMON_H__
#define NRF_DRV_COMMON_H__
#include <nrfx.h>
#ifdef __cplusplus
extern "C" {
#endif
#define INTERRUPT_PRIORITY_VALIDATION(pri) STATIC_ASSERT(INTERRUPT_PRIORITY_IS_VALID((pri)))
#define INTERRUPT_PRIORITY_ASSERT(pri) ASSERT(INTERRUPT_PRIORITY_IS_VALID((pri)))
#define nrf_drv_irq_handler_t nrfx_irq_handler_t
#define nrf_drv_bitpos_to_event nrfx_bitpos_to_event
#define nrf_drv_event_to_bitpos nrfx_event_to_bitpos
#define nrf_drv_get_IRQn nrfx_get_irq_number
#define nrf_drv_is_in_RAM nrfx_is_in_ram
#ifdef __cplusplus
}
#endif
#endif // NRF_DRV_COMMON_H__

View File

@ -0,0 +1,139 @@
/**
* 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 NRF_DRV_GPIOTE_H__
#define NRF_DRV_GPIOTE_H__
#include <nrfx_gpiote.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup nrf_drv_gpiote GPIOTE driver - legacy layer
* @{
* @ingroup nrf_gpiote
* @brief Layer providing compatibility with the former API.
*/
/** @brief Type definition for forwarding the new implementation. */
typedef nrfx_gpiote_in_config_t nrf_drv_gpiote_in_config_t;
/** @brief Type definition for forwarding the new implementation. */
typedef nrfx_gpiote_pin_t nrf_drv_gpiote_pin_t;
/** @brief Type definition for forwarding the new implementation. */
typedef nrfx_gpiote_out_config_t nrf_drv_gpiote_out_config_t;
/** @brief Type definition for forwarding the new implementation. */
typedef nrfx_gpiote_evt_handler_t nrf_drv_gpiote_evt_handler_t;
/** @brief Macro for forwarding the new implementation. */
#define GPIOTE_CONFIG_IN_SENSE_LOTOHI NRFX_GPIOTE_CONFIG_IN_SENSE_LOTOHI
/** @brief Macro for forwarding the new implementation. */
#define GPIOTE_CONFIG_IN_SENSE_HITOLO NRFX_GPIOTE_CONFIG_IN_SENSE_HITOLO
/** @brief Macro for forwarding the new implementation. */
#define GPIOTE_CONFIG_IN_SENSE_TOGGLE NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE
/** @brief Macro for forwarding the new implementation. */
#define GPIOTE_RAW_CONFIG_IN_SENSE_LOTOHI NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_LOTOHI
/** @brief Macro for forwarding the new implementation. */
#define GPIOTE_RAW_CONFIG_IN_SENSE_HITOLO NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_HITOLO
/** @brief Macro for forwarding the new implementation. */
#define GPIOTE_RAW_CONFIG_IN_SENSE_TOGGLE NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_TOGGLE
/** @brief Macro for forwarding the new implementation. */
#define GPIOTE_CONFIG_OUT_SIMPLE NRFX_GPIOTE_CONFIG_OUT_SIMPLE
/** @brief Macro for forwarding the new implementation. */
#define GPIOTE_CONFIG_OUT_TASK_LOW NRFX_GPIOTE_CONFIG_OUT_TASK_LOW
/** @brief Macro for forwarding the new implementation. */
#define GPIOTE_CONFIG_OUT_TASK_HIGH NRFX_GPIOTE_CONFIG_OUT_TASK_HIGH
/** @brief Macro for forwarding the new implementation. */
#define GPIOTE_CONFIG_OUT_TASK_TOGGLE NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_init nrfx_gpiote_init
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_is_init nrfx_gpiote_is_init
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_uninit nrfx_gpiote_uninit
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_out_init nrfx_gpiote_out_init
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_out_uninit nrfx_gpiote_out_uninit
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_out_set nrfx_gpiote_out_set
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_out_clear nrfx_gpiote_out_clear
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_out_toggle nrfx_gpiote_out_toggle
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_out_task_enable nrfx_gpiote_out_task_enable
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_out_task_disable nrfx_gpiote_out_task_disable
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_out_task_addr_get nrfx_gpiote_out_task_addr_get
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_in_init nrfx_gpiote_in_init
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_in_uninit nrfx_gpiote_in_uninit
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_in_event_enable nrfx_gpiote_in_event_enable
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_in_event_disable nrfx_gpiote_in_event_disable
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_in_is_set nrfx_gpiote_in_is_set
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_in_event_addr_get nrfx_gpiote_in_event_addr_get
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_set_task_addr_get nrfx_gpiote_set_task_addr_get
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_clr_task_addr_get nrfx_gpiote_clr_task_addr_get
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_out_task_force nrfx_gpiote_out_task_force
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_out_task_trigger nrfx_gpiote_out_task_trigger
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_set_task_trigger nrfx_gpiote_set_task_trigger
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_gpiote_clr_task_trigger nrfx_gpiote_clr_task_trigger
/** @} */
#ifdef __cplusplus
}
#endif
#endif //NRF_DRV_GPIOTE_H__

View File

@ -0,0 +1,135 @@
/**
* 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 NRF_DRV_PWM_H__
#define NRF_DRV_PWM_H__
#include <nrfx_pwm.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup nrf_drv_pwm PWM driver - legacy layer
* @{
* @ingroup nrf_pwm
*
* @brief @tagAPI52 Layer providing compatibility with the former API.
*/
/** @brief Type definition for forwarding the new implementation. */
typedef nrfx_pwm_t nrf_drv_pwm_t;
/** @brief Type definition for forwarding the new implementation. */
typedef nrfx_pwm_config_t nrf_drv_pwm_config_t;
/** @brief Macro for forwarding the new implementation. */
#define NRF_DRV_PWM_INSTANCE NRFX_PWM_INSTANCE
/** @brief Macro for forwarding the new implementation. */
#define NRF_DRV_PWM_PIN_NOT_USED NRFX_PWM_PIN_NOT_USED
/** @brief Macro for forwarding the new implementation. */
#define NRF_DRV_PWM_PIN_INVERTED NRFX_PWM_PIN_INVERTED
/** @brief Macro for forwarding the new implementation. */
#define NRF_DRV_PWM_DEFAULT_CONFIG NRFX_PWM_DEFAULT_CONFIG
/** @brief Macro for forwarding the new implementation. */
#define NRF_DRV_PWM_FLAG_STOP NRFX_PWM_FLAG_STOP
/** @brief Macro for forwarding the new implementation. */
#define NRF_DRV_PWM_FLAG_LOOP NRFX_PWM_FLAG_LOOP
/** @brief Macro for forwarding the new implementation. */
#define NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ0 NRFX_PWM_FLAG_SIGNAL_END_SEQ0
/** @brief Macro for forwarding the new implementation. */
#define NRF_DRV_PWM_FLAG_SIGNAL_END_SEQ1 NRFX_PWM_FLAG_SIGNAL_END_SEQ1
/** @brief Macro for forwarding the new implementation. */
#define NRF_DRV_PWM_FLAG_NO_EVT_FINISHED NRFX_PWM_FLAG_NO_EVT_FINISHED
/** @brief Macro for forwarding the new implementation. */
#define NRF_DRV_PWM_FLAG_START_VIA_TASK NRFX_PWM_FLAG_START_VIA_TASK
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_pwm_flag_t nrfx_pwm_flag_t
/** @brief Macro for forwarding the new implementation. */
#define NRF_DRV_PWM_EVT_FINISHED NRFX_PWM_EVT_FINISHED
/** @brief Macro for forwarding the new implementation. */
#define NRF_DRV_PWM_EVT_END_SEQ0 NRFX_PWM_EVT_END_SEQ0
/** @brief Macro for forwarding the new implementation. */
#define NRF_DRV_PWM_EVT_END_SEQ1 NRFX_PWM_EVT_END_SEQ1
/** @brief Macro for forwarding the new implementation. */
#define NRF_DRV_PWM_EVT_STOPPED NRFX_PWM_EVT_STOPPED
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_pwm_evt_type_t nrfx_pwm_evt_type_t
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_pwm_handler_t nrfx_pwm_handler_t
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_pwm_init nrfx_pwm_init
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_pwm_uninit nrfx_pwm_uninit
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_pwm_simple_playback nrfx_pwm_simple_playback
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_pwm_complex_playback nrfx_pwm_complex_playback
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_pwm_step nrfx_pwm_step
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_pwm_stop nrfx_pwm_stop
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_pwm_is_stopped nrfx_pwm_is_stopped
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_pwm_sequence_update nrfx_pwm_sequence_update
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_pwm_sequence_values_update nrfx_pwm_sequence_values_update
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_pwm_sequence_length_update nrfx_pwm_sequence_length_update
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_pwm_sequence_repeats_update nrfx_pwm_sequence_repeats_update
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_pwm_sequence_end_delay_update nrfx_pwm_sequence_end_delay_update
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_pwm_task_address_get nrfx_pwm_task_address_get
/** @brief Macro for forwarding the new implementation. */
#define nrf_drv_pwm_event_address_get nrfx_pwm_event_address_get
/** @} */
#ifdef __cplusplus
}
#endif
#endif // NRF_DRV_PWM_H__

Some files were not shown because too many files have changed in this diff Show More