Merge pull request #13691 from jrobeson/drop-nordic-sdk11

Remove unused Nordic TARGET_SDK_11
pull/13904/head
Martin Kojtal 2020-11-12 09:35:42 +00:00 committed by GitHub
commit 76ff098e94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
182 changed files with 2 additions and 80485 deletions

View File

@ -90,14 +90,6 @@ void gpio_init(gpio_t *obj, PinName pin)
m_gpio_cfg[obj->pin].used_as_gpio = true; m_gpio_cfg[obj->pin].used_as_gpio = true;
} }
#ifdef TARGET_SDK_11
// implement polyfill of gpio hal for the nRF5 SDK v11
__STATIC_INLINE uint32_t nrf_gpio_pin_out_read(uint32_t pin)
{
return (NRF_GPIO->OUTSET & (1UL << (pin)));
}
#endif
int gpio_read(gpio_t *obj) int gpio_read(gpio_t *obj)
{ {
MBED_ASSERT(obj->pin != (PinName)NC); MBED_ASSERT(obj->pin != (PinName)NC);

View File

@ -1,594 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ble_advdata.h"
#include "ble_advertising.h"
#include "nrf_soc.h"
#include "nrf_log.h"
#include "pstorage.h"
#include "fstorage.h"
#include "sdk_common.h"
#define ADV_LOG(...)
static bool m_advertising_start_pending = false; /**< Flag to keep track of ongoing operations on persistent memory. */
static ble_gap_addr_t m_peer_address; /**< Address of the most recently connected peer, used for direct advertising. */
static ble_advdata_t m_advdata; /**< Used by the initialization function to set name, appearance, and UUIDs and advertising flags visible to peer devices. */
static ble_adv_evt_t m_adv_evt; /**< Advertising event propogated to the main application. The event is either a transaction to a new advertising mode, or a request for whitelist or peer address.. */
static ble_advertising_evt_handler_t m_evt_handler; /**< Handler for the advertising events. Can be initialized as NULL if no handling is implemented on in the main application. */
static ble_advertising_error_handler_t m_error_handler; /**< Handler for the advertising error events. */
static ble_adv_mode_t m_adv_mode_current; /**< Variable to keep track of the current advertising mode. */
static ble_adv_modes_config_t m_adv_modes_config; /**< Struct to keep track of disabled and enabled advertising modes, as well as time-outs and intervals.*/
static ble_gap_whitelist_t m_whitelist; /**< Struct that points to whitelisted addresses. */
static ble_gap_addr_t * mp_whitelist_addr[BLE_GAP_WHITELIST_ADDR_MAX_COUNT]; /**< Pointer to a list of addresses. Pointed to by the whitelist */
static ble_gap_irk_t * mp_whitelist_irk[BLE_GAP_WHITELIST_IRK_MAX_COUNT]; /**< Pointer to a list of Identity Resolving Keys (IRK). Pointed to by the whitelist */
static bool m_whitelist_temporarily_disabled = false; /**< Flag to keep track of temporary disabling of the whitelist. */
static bool m_whitelist_reply_expected = false; /**< Flag to verify that whitelist is only set when it is requested. */
static bool m_peer_addr_reply_expected = false; /**< Flag to verify that peer address is only set when requested. */
static ble_advdata_manuf_data_t m_manuf_specific_data; /**< Manufacturer specific data structure*/
static uint8_t m_manuf_data_array[BLE_GAP_ADV_MAX_SIZE]; /**< Array to store the Manufacturer specific data*/
static ble_advdata_service_data_t m_service_data; /**< Service data structure. */
static uint8_t m_service_data_array[BLE_GAP_ADV_MAX_SIZE]; /**< Array to store the service data. */
static ble_advdata_conn_int_t m_slave_conn_int; /**< Connection interval range structure.*/
static int8_t m_tx_power_level; /**< TX power level*/
/**@brief Function for checking that the whitelist has entries.
*/
static bool whitelist_has_entries(ble_gap_whitelist_t const * whitelist)
{
if ((whitelist->addr_count != 0) || (whitelist->irk_count != 0))
{
return true;
}
return false;
}
/**@brief Function for setting the stored peer address back to zero.
*/
static void ble_advertising_peer_address_clear()
{
memset(&m_peer_address, 0, sizeof(m_peer_address));
}
/**@brief Function for checking if an address is non-zero. Used to determine if
*/
static bool peer_address_exists(uint8_t const * address)
{
uint32_t i;
for (i = 0; i < BLE_GAP_ADDR_LEN; i++)
{
if (address[i] != 0)
{
return true;
}
}
return false;
}
uint32_t ble_advertising_init(ble_advdata_t const * p_advdata,
ble_advdata_t const * p_srdata,
ble_adv_modes_config_t const * p_config,
ble_advertising_evt_handler_t const evt_handler,
ble_advertising_error_handler_t const error_handler)
{
uint32_t err_code;
VERIFY_PARAM_NOT_NULL(p_advdata);
VERIFY_PARAM_NOT_NULL(p_config);
m_adv_mode_current = BLE_ADV_MODE_IDLE;
m_evt_handler = evt_handler;
m_error_handler = error_handler;
m_adv_modes_config = *p_config;
ble_advertising_peer_address_clear();
// Prepare Whitelist. Address and IRK double pointers point to allocated arrays.
m_whitelist.pp_addrs = mp_whitelist_addr;
m_whitelist.pp_irks = mp_whitelist_irk;
// Copy and set advertising data.
memset(&m_advdata, 0, sizeof(m_advdata));
// Copy advertising data.
m_advdata.name_type = p_advdata->name_type;
m_advdata.include_appearance = p_advdata->include_appearance;
m_advdata.flags = p_advdata->flags;
m_advdata.short_name_len = p_advdata->short_name_len;
/*
if(p_advdata->uuids_complete != NULL)
{
m_advdata.uuids_complete = p_advdata->uuids_complete;
}
*/
m_advdata.uuids_complete = p_advdata->uuids_complete;
m_advdata.uuids_more_available = p_advdata->uuids_more_available;
m_advdata.uuids_solicited = p_advdata->uuids_solicited;
if(p_advdata->p_manuf_specific_data != NULL)
{
m_advdata.p_manuf_specific_data = &m_manuf_specific_data;
m_manuf_specific_data.data.p_data = m_manuf_data_array;
m_advdata.p_manuf_specific_data->company_identifier =
p_advdata->p_manuf_specific_data->company_identifier;
m_advdata.p_manuf_specific_data->data.size = p_advdata->p_manuf_specific_data->data.size;
for(uint32_t i = 0; i < m_advdata.p_manuf_specific_data->data.size; i++)
{
m_manuf_data_array[i] = p_advdata->p_manuf_specific_data->data.p_data[i];
}
}
if(p_advdata->p_service_data_array != NULL)
{
m_service_data.data.p_data = m_service_data_array;
m_advdata.p_service_data_array = &m_service_data;
m_advdata.p_service_data_array->data.p_data = m_service_data_array;
m_advdata.p_service_data_array->data.size = p_advdata->p_service_data_array->data.size;
m_advdata.p_service_data_array->service_uuid = p_advdata->p_service_data_array->service_uuid;
for(uint32_t i = 0; i < m_advdata.p_service_data_array->data.size; i++)
{
m_service_data_array[i] = p_advdata->p_service_data_array->data.p_data[i];
}
m_advdata.service_data_count = p_advdata->service_data_count;
}
if(p_advdata->p_slave_conn_int != NULL)
{
m_advdata.p_slave_conn_int = &m_slave_conn_int;
m_advdata.p_slave_conn_int->max_conn_interval = p_advdata->p_slave_conn_int->max_conn_interval;
m_advdata.p_slave_conn_int->min_conn_interval = p_advdata->p_slave_conn_int->min_conn_interval;
}
if(p_advdata->p_tx_power_level != NULL)
{
m_advdata.p_tx_power_level = &m_tx_power_level;
m_advdata.p_tx_power_level = p_advdata->p_tx_power_level;
}
err_code = ble_advdata_set(&m_advdata, p_srdata);
return err_code;
}
/** @brief Function to determine if a flash access in in progress. If it is the case, we can not
* start advertising until it is finished. attempted restart
* in @ref ble_advertising_on_sys_evt
*
* @return true if a flash access is in progress, false if not.
*/
static bool flash_access_in_progress()
{
uint32_t err_code;
uint32_t count = 0;
err_code = pstorage_access_status_get(&count);
if ((err_code != NRF_ERROR_INVALID_STATE) && (err_code != NRF_SUCCESS))
{
ADV_LOG("[ADV]: pstorage_access_status_get returned %d.\r\n", err_code);
return true;
}
if (err_code == NRF_ERROR_INVALID_STATE)
{
err_code = fs_queued_op_count_get(&count);
if (err_code != FS_SUCCESS)
{
return false;
}
ADV_LOG("[ADV]: fs_queued_op_count_get gives count %d.\r\n", count);
}
if(count != 0)
{
return true;
}
else
{
return false;
}
}
uint32_t ble_advertising_start(ble_adv_mode_t advertising_mode)
{
uint32_t err_code;
ble_gap_adv_params_t adv_params;
m_adv_mode_current = advertising_mode;
// Verify if there are any pending flash operations. If so, delay starting advertising until
// the flash operations are complete.
if(flash_access_in_progress())
{
m_advertising_start_pending = true;
return NRF_SUCCESS;
}
ADV_LOG("[ADV]: no flash operations in progress, prepare advertising.\r\n");
// Fetch the peer address.
ble_advertising_peer_address_clear();
if ( ((m_adv_modes_config.ble_adv_directed_enabled) && (m_adv_mode_current == BLE_ADV_MODE_DIRECTED))
||((m_adv_modes_config.ble_adv_directed_slow_enabled) && (m_adv_mode_current == BLE_ADV_MODE_DIRECTED))
||((m_adv_modes_config.ble_adv_directed_slow_enabled) && (m_adv_mode_current == BLE_ADV_MODE_DIRECTED_SLOW))
)
{
if (m_evt_handler != NULL)
{
m_peer_addr_reply_expected = true;
m_evt_handler(BLE_ADV_EVT_PEER_ADDR_REQUEST);
}
else
{
m_peer_addr_reply_expected = false;
}
}
// If a mode is disabled, continue to the next mode. I.e fast instead of direct, slow instead of fast, idle instead of slow.
if ( (m_adv_mode_current == BLE_ADV_MODE_DIRECTED)
&&(!m_adv_modes_config.ble_adv_directed_enabled || !peer_address_exists(m_peer_address.addr)))
{
m_adv_mode_current = BLE_ADV_MODE_DIRECTED_SLOW;
}
if ( (m_adv_mode_current == BLE_ADV_MODE_DIRECTED_SLOW)
&&(!m_adv_modes_config.ble_adv_directed_slow_enabled || !peer_address_exists(m_peer_address.addr)))
{
m_adv_mode_current = BLE_ADV_MODE_FAST;
}
if (!m_adv_modes_config.ble_adv_fast_enabled && m_adv_mode_current == BLE_ADV_MODE_FAST)
{
m_adv_mode_current = BLE_ADV_MODE_SLOW;
}
if (!m_adv_modes_config.ble_adv_slow_enabled && m_adv_mode_current == BLE_ADV_MODE_SLOW)
{
m_adv_mode_current = BLE_ADV_MODE_IDLE;
m_adv_evt = BLE_ADV_EVT_IDLE;
}
// Fetch the whitelist.
if ( (m_evt_handler != NULL)
&& (m_adv_mode_current == BLE_ADV_MODE_FAST || m_adv_mode_current == BLE_ADV_MODE_SLOW)
&& (m_adv_modes_config.ble_adv_whitelist_enabled)
&& (!m_whitelist_temporarily_disabled))
{
m_whitelist_reply_expected = true;
m_evt_handler(BLE_ADV_EVT_WHITELIST_REQUEST);
}
else
{
m_whitelist_reply_expected = false;
}
// Initialize advertising parameters with default values.
memset(&adv_params, 0, sizeof(adv_params));
adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND;
adv_params.p_peer_addr = NULL;
adv_params.fp = BLE_GAP_ADV_FP_ANY;
adv_params.p_whitelist = NULL;
// Set advertising parameters and events according to selected advertising mode.
switch (m_adv_mode_current)
{
case BLE_ADV_MODE_DIRECTED:
ADV_LOG("[ADV]: Starting direct advertisement.\r\n");
adv_params.p_peer_addr = &m_peer_address; // Directed advertising.
adv_params.type = BLE_GAP_ADV_TYPE_ADV_DIRECT_IND;
adv_params.timeout = 0;
adv_params.interval = 0;
m_adv_evt = BLE_ADV_EVT_DIRECTED;
break;
case BLE_ADV_MODE_DIRECTED_SLOW:
ADV_LOG("[ADV]: Starting direct advertisement.\r\n");
adv_params.p_peer_addr = &m_peer_address; // Directed advertising.
adv_params.type = BLE_GAP_ADV_TYPE_ADV_DIRECT_IND;
adv_params.timeout = m_adv_modes_config.ble_adv_directed_slow_timeout;
adv_params.interval = m_adv_modes_config.ble_adv_directed_slow_interval;
m_adv_evt = BLE_ADV_EVT_DIRECTED_SLOW;
break;
case BLE_ADV_MODE_FAST:
adv_params.timeout = m_adv_modes_config.ble_adv_fast_timeout;
adv_params.interval = m_adv_modes_config.ble_adv_fast_interval;
if ( whitelist_has_entries(&m_whitelist)
&& m_adv_modes_config.ble_adv_whitelist_enabled
&& !m_whitelist_temporarily_disabled)
{
adv_params.fp = BLE_GAP_ADV_FP_FILTER_CONNREQ;
adv_params.p_whitelist = &m_whitelist;
m_advdata.flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
err_code = ble_advdata_set(&m_advdata, NULL);
VERIFY_SUCCESS(err_code);
m_adv_evt = BLE_ADV_EVT_FAST_WHITELIST;
ADV_LOG("[ADV]: Starting fast advertisement with whitelist.\r\n");
}
else
{
m_adv_evt = BLE_ADV_EVT_FAST;
ADV_LOG("[ADV]: Starting fast advertisement.\r\n");
}
break;
case BLE_ADV_MODE_SLOW:
adv_params.interval = m_adv_modes_config.ble_adv_slow_interval;
adv_params.timeout = m_adv_modes_config.ble_adv_slow_timeout;
if ( whitelist_has_entries(&m_whitelist)
&& m_adv_modes_config.ble_adv_whitelist_enabled
&& !m_whitelist_temporarily_disabled)
{
adv_params.fp = BLE_GAP_ADV_FP_FILTER_CONNREQ;
adv_params.p_whitelist = &m_whitelist;
m_advdata.flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
err_code = ble_advdata_set(&m_advdata, NULL);
VERIFY_SUCCESS(err_code);
m_adv_evt = BLE_ADV_EVT_SLOW_WHITELIST;
ADV_LOG("[ADV]: Starting slow advertisement with whitelist.\r\n");
}
else
{
m_adv_evt = BLE_ADV_EVT_SLOW;
ADV_LOG("[ADV]: Starting slow advertisement.\r\n");
}
break;
default:
break;
}
if (m_adv_mode_current != BLE_ADV_MODE_IDLE)
{
err_code = sd_ble_gap_adv_start(&adv_params);
VERIFY_SUCCESS(err_code);
}
if (m_evt_handler != NULL)
{
m_evt_handler(m_adv_evt);
}
return NRF_SUCCESS;
}
void ble_advertising_on_ble_evt(ble_evt_t const * p_ble_evt)
{
static uint16_t current_slave_link_conn_handle = BLE_CONN_HANDLE_INVALID;
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
if (p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_PERIPH)
{
current_slave_link_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
}
break;
// Upon disconnection, whitelist will be activated and direct advertising is started.
case BLE_GAP_EVT_DISCONNECTED:
{
uint32_t err_code;
m_whitelist_temporarily_disabled = false;
if (p_ble_evt->evt.gap_evt.conn_handle == current_slave_link_conn_handle)
{
err_code = ble_advertising_start(BLE_ADV_MODE_DIRECTED);
if ((err_code != NRF_SUCCESS) && (m_error_handler != NULL))
{
m_error_handler(err_code);
}
}
break;
}
// Upon time-out, the next advertising mode is started, i.e. go from fast to slow or from slow to idle.
case BLE_GAP_EVT_TIMEOUT:
if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISING)
{
switch (m_adv_mode_current)
{
case BLE_ADV_MODE_DIRECTED:
ADV_LOG("[ADV]: Timed out from directed advertising.\r\n");
{
uint32_t err_code;
err_code = ble_advertising_start(BLE_ADV_MODE_DIRECTED_SLOW);
if ((err_code != NRF_SUCCESS) && (m_error_handler != NULL))
{
m_error_handler(err_code);
}
}
break;
case BLE_ADV_MODE_DIRECTED_SLOW:
ADV_LOG("[ADV]: Timed out from directed slow advertising.\r\n");
{
uint32_t err_code;
err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
if ((err_code != NRF_SUCCESS) && (m_error_handler != NULL))
{
m_error_handler(err_code);
}
}
break;
case BLE_ADV_MODE_FAST:
{
uint32_t err_code;
m_adv_evt = BLE_ADV_EVT_FAST;
ADV_LOG("[ADV]: Timed out from fast advertising, starting slow advertising.\r\n");
err_code = ble_advertising_start(BLE_ADV_MODE_SLOW);
if ((err_code != NRF_SUCCESS) && (m_error_handler != NULL))
{
m_error_handler(err_code);
}
break;
}
case BLE_ADV_MODE_SLOW:
m_adv_evt = BLE_ADV_EVT_IDLE;
ADV_LOG("[ADV]: Timed out from slow advertising, stopping advertising.\r\n");
if (m_evt_handler != NULL)
{
m_evt_handler(m_adv_evt);
}
break;
default:
// No implementation needed.
break;
}
}
break;
default:
// No implementation needed.
break;
}
}
void ble_advertising_on_sys_evt(uint32_t sys_evt)
{
uint32_t err_code = NRF_SUCCESS;
switch (sys_evt)
{
case NRF_EVT_FLASH_OPERATION_SUCCESS:
// Fall through.
//When a flash operation finishes, advertising no longer needs to be pending.
case NRF_EVT_FLASH_OPERATION_ERROR:
if (m_advertising_start_pending)
{
m_advertising_start_pending = false;
err_code = ble_advertising_start(m_adv_mode_current);
if ((err_code != NRF_SUCCESS) && (m_error_handler != NULL))
{
m_error_handler(err_code);
}
}
break;
default:
// No implementation needed.
break;
}
}
uint32_t ble_advertising_peer_addr_reply(ble_gap_addr_t * p_peer_address)
{
if(m_peer_addr_reply_expected == false)
{
return NRF_ERROR_INVALID_STATE;
}
m_peer_address.addr_type = p_peer_address->addr_type;
for (int i = 0; i < BLE_GAP_ADDR_LEN; i++)
{
m_peer_address.addr[i] = p_peer_address->addr[i];
}
m_peer_addr_reply_expected = false;
return NRF_SUCCESS;
}
uint32_t ble_advertising_whitelist_reply(ble_gap_whitelist_t * p_whitelist)
{
uint32_t i;
if(m_whitelist_reply_expected == false)
{
return NRF_ERROR_INVALID_STATE;
}
m_whitelist.addr_count = p_whitelist->addr_count;
m_whitelist.irk_count = p_whitelist->irk_count;
for (i = 0; i < m_whitelist.irk_count; i++)
{
mp_whitelist_irk[i] = p_whitelist->pp_irks[i];
}
for (i = 0; i < m_whitelist.addr_count; i++)
{
mp_whitelist_addr[i] = p_whitelist->pp_addrs[i];
}
m_whitelist_reply_expected = false;
return NRF_SUCCESS;
}
uint32_t ble_advertising_restart_without_whitelist(void)
{
uint32_t err_code;
if( m_adv_modes_config.ble_adv_whitelist_enabled == BLE_ADV_WHITELIST_ENABLED
&& !m_whitelist_temporarily_disabled)
{
if (m_adv_mode_current != BLE_ADV_MODE_IDLE)
{
err_code = sd_ble_gap_adv_stop();
VERIFY_SUCCESS(err_code);
}
m_whitelist_temporarily_disabled = true;
m_advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
err_code = ble_advdata_set(&m_advdata, NULL);
VERIFY_SUCCESS(err_code);
err_code = ble_advertising_start(m_adv_mode_current);
if ((err_code != NRF_SUCCESS) && (m_error_handler != NULL))
{
m_error_handler(err_code);
}
}
return NRF_SUCCESS;
}

View File

@ -1,251 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**@file
*
* @defgroup ble_sdk_lib_advertising Advertising Module
* @{
* @ingroup ble_sdk_lib
* @brief Module for handling connectable BLE advertising.
*
* @details The Advertising Module handles connectable advertising for your application. It can
* be configured with advertising modes to suit most typical use cases.
* Your main application can react to changes in advertising modes
* if an event handler is provided.
*
* @note The Advertising Module supports only applications with a single peripheral link.
*
* The application must propagate BLE stack events to this module by calling
* @ref ble_advertising_on_ble_evt() and system events by calling
* @ref ble_advertising_on_sys_evt().
*
*/
#ifndef BLE_ADVERTISING_H__
#define BLE_ADVERTISING_H__
#include <stdint.h>
#include "nrf_ble_gattc.h"
#include "nrf_ble.h"
#include "nrf_error.h"
#include "ble_advdata.h"
/**@brief Advertising modes.
*/
typedef enum
{
BLE_ADV_MODE_IDLE, /**< Idle; no connectable advertising is ongoing.*/
BLE_ADV_MODE_DIRECTED, /**< Directed advertising attempts to connect to the most recently disconnected peer. */
BLE_ADV_MODE_DIRECTED_SLOW, /**< Directed advertising (low duty cycle) attempts to connect to the most recently disconnected peer. */
BLE_ADV_MODE_FAST, /**< Fast advertising will connect to any peer device, or filter with a whitelist if one exists. */
BLE_ADV_MODE_SLOW, /**< Slow advertising is similar to fast advertising. By default, it uses a longer advertising interval and time-out than fast advertising. However, these options are defined by the user. */
} ble_adv_mode_t;
/**@brief Advertising events.
*
* @details These events are propagated to the main application if a handler was provided during
* initialization of the Advertising Module. Events for modes that are not used can be
* ignored. Similarly, BLE_ADV_EVT_WHITELIST_REQUEST and BLE_ADV_EVT_PEER_ADDR_REQUEST
* can be ignored if whitelist and direct advertising is not used.
*/
typedef enum
{
BLE_ADV_EVT_IDLE, /**< Idle; no connectable advertising is ongoing.*/
BLE_ADV_EVT_DIRECTED, /**< Direct advertising mode has started. */
BLE_ADV_EVT_DIRECTED_SLOW, /**< Directed advertising (low duty cycle) has started. */
BLE_ADV_EVT_FAST, /**< Fast advertising mode has started. */
BLE_ADV_EVT_SLOW, /**< Slow advertising mode has started.*/
BLE_ADV_EVT_FAST_WHITELIST, /**< Fast advertising mode using the whitelist has started. */
BLE_ADV_EVT_SLOW_WHITELIST, /**< Slow advertising mode using the whitelist has started.*/
BLE_ADV_EVT_WHITELIST_REQUEST, /**< Request a whitelist from the main application. For whitelist advertising to work, the whitelist must be set when this event occurs. */
BLE_ADV_EVT_PEER_ADDR_REQUEST /**< Request a peer address from the main application. For directed advertising to work, the peer address must be set when this event occurs. */
} ble_adv_evt_t;
/**@brief Options for the different advertisement modes.
*
* @details This structure is used to enable or disable advertising modes and to configure time-out
* periods and advertising intervals.
*/
typedef struct
{
bool ble_adv_whitelist_enabled; /**< Enable or disable use of the whitelist. */
bool ble_adv_directed_enabled; /**< Enable or disable direct advertising mode. */
bool ble_adv_directed_slow_enabled; /**< Enable or disable direct advertising mode. */
uint32_t ble_adv_directed_slow_interval; /**< Advertising interval for directed advertising. */
uint32_t ble_adv_directed_slow_timeout; /**< Time-out (number of tries) for direct advertising. */
bool ble_adv_fast_enabled; /**< Enable or disable fast advertising mode. */
uint32_t ble_adv_fast_interval; /**< Advertising interval for fast advertising. */
uint32_t ble_adv_fast_timeout; /**< Time-out (in seconds) for fast advertising. */
bool ble_adv_slow_enabled; /**< Enable or disable slow advertising mode. */
uint32_t ble_adv_slow_interval; /**< Advertising interval for slow advertising. */
uint32_t ble_adv_slow_timeout; /**< Time-out (in seconds) for slow advertising. */
}ble_adv_modes_config_t;
/**@brief BLE advertising event handler type. */
typedef void (*ble_advertising_evt_handler_t) (ble_adv_evt_t const adv_evt);
/**@brief BLE advertising error handler type. */
typedef void (*ble_advertising_error_handler_t) (uint32_t nrf_error);
/**@brief Initialization parameters for the Advertising Module.
* @details This structure is used to pass advertising options, advertising data, and an event handler to the Advertising Module during initialization. */
typedef struct
{
ble_adv_modes_config_t options; /**< Parameters for advertising modes.*/
ble_advdata_t advdata; /**< Advertising data. */
ble_advertising_evt_handler_t evt_handler; /**< Event handler. */
}ble_adv_init_t;
/* Defines to make the mode options easier to set during advertising init.*/
#define BLE_ADV_DIRECTED_ENABLED true
#define BLE_ADV_DIRECTED_DISABLED false
#define BLE_ADV_DIRECTED_SLOW_ENABLED true
#define BLE_ADV_DIRECTED_SLOW_DISABLED false
#define BLE_ADV_FAST_ENABLED true
#define BLE_ADV_FAST_DISABLED false
#define BLE_ADV_SLOW_ENABLED true
#define BLE_ADV_SLOW_DISABLED false
#define BLE_ADV_WHITELIST_ENABLED true
#define BLE_ADV_WHITELIST_DISABLED false
/**@brief Function for handling BLE events.
*
* @details This function must be called from the BLE stack event dispatcher for
* the module to handle BLE events that are relevant for the Advertising Module.
*
* @param[in] p_ble_evt BLE stack event.
*/
void ble_advertising_on_ble_evt(const ble_evt_t * const p_ble_evt);
/**@brief Function for handling system events.
*
* @details This function must be called to handle system events that are relevant
* for the Advertising Module. Specifically, the advertising module can not use the
* softdevice as long as there are pending writes to the flash memory. This
* event handler is designed to delay advertising until there is no flash operation.
*
* @param[in] sys_evt System event.
*/
void ble_advertising_on_sys_evt(uint32_t sys_evt);
/**@brief Function for initializing the Advertising Module.
*
* @details Encodes the required advertising data and passes it to the stack.
* Also builds a structure to be passed to the stack when starting advertising.
* The supplied advertising data is copied to a local structure and is manipulated
* depending on what advertising modes are started in @ref ble_advertising_start.
*
* @param[in] p_advdata Advertising data: name, appearance, discovery flags, and more.
* @param[in] p_srdata Scan response data: Supplement to advertising data.
* @param[in] p_config Select which advertising modes and intervals will be utilized.
* @param[in] evt_handler Event handler that will be called upon advertising events.
* @param[in] error_handler Error handler that will propogate internal errors to the main applications.
*
* @retval NRF_SUCCESS If initialization was successful. Otherwise, an error code is returned.
*/
uint32_t ble_advertising_init(ble_advdata_t const * p_advdata,
ble_advdata_t const * p_srdata,
ble_adv_modes_config_t const * p_config,
ble_advertising_evt_handler_t const evt_handler,
ble_advertising_error_handler_t const error_handler);
/**@brief Function for starting advertising.
*
* @details You can start advertising in any of the advertising modes that you enabled
* during initialization.
*
* @param[in] advertising_mode Advertising mode.
*
* @retval @ref NRF_SUCCESS On success, else an error code indicating reason for failure.
* @retval @ref NRF_ERROR_INVALID_STATE
*/
uint32_t ble_advertising_start(ble_adv_mode_t advertising_mode);
/**@brief Function for setting the peer address.
*
* @details The peer address must be set by the application upon receiving a
* @ref BLE_ADV_EVT_PEER_ADDR_REQUEST event. Without the peer address, the directed
* advertising mode will not be run.
*
* @param[in] p_peer_addr Pointer to a peer address.
*
* @retval @ref NRF_SUCCESS Successfully stored the peer address pointer in the advertising module.
* @retval @ref NRF_ERROR_INVALID_STATE If a reply was not expected.
*/
uint32_t ble_advertising_peer_addr_reply(ble_gap_addr_t * p_peer_addr);
/**@brief Function for setting a whitelist.
*
* @details The whitelist must be set by the application upon receiving a
* @ref BLE_ADV_EVT_WHITELIST_REQUEST event. Without the whitelist, the whitelist
* advertising for fast and slow modes will not be run.
*
* @param[in] p_whitelist Pointer to a whitelist.
*
* @retval @ref NRF_SUCCESS Successfully stored pointers to the whitelist into the advertising module.
* @retval @ref NRF_ERROR_INVALID_STATE If a reply was not expected.
*/
uint32_t ble_advertising_whitelist_reply(ble_gap_whitelist_t * p_whitelist);
/**@brief Function for disabling whitelist advertising.
*
* @details This function temporarily disables whitelist advertising.
* Calling this function resets the current time-out countdown.
*
* @retval @ref NRF_SUCCESS On success, else an error message propogated from the Softdevice.
*/
uint32_t ble_advertising_restart_without_whitelist(void);
/** @} */
#endif // BLE_ADVERTISING_H__
/** @} */

View File

@ -1,967 +0,0 @@
/*
* Copyright (c) 2013 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ble_db_discovery.h"
#include <stdlib.h>
#include "nrf_ble.h"
#include "nrf_log.h"
#include "sdk_common.h"
#define SRV_DISC_START_HANDLE 0x0001 /**< The start handle value used during service discovery. */
#define DB_DISCOVERY_MAX_USERS BLE_DB_DISCOVERY_MAX_SRV /**< The maximum number of users/registrations allowed by this module. */
#define DB_LOG NRF_LOG_PRINTF_DEBUG /**< A debug logger macro that can be used in this file to do logging information over UART. */
/**@brief Array of structures containing information about the registered application modules. */
static ble_uuid_t m_registered_handlers[DB_DISCOVERY_MAX_USERS];
/**@brief Array of structures containing pending events to be sent to the application modules.
*
* @details Whenever a discovery related event is to be raised to a user module, it will be stored
* in this array first. When all services needed to be discovered have been
* discovered, all pending events will be sent to the corresponding user modules.
**/
static struct
{
ble_db_discovery_evt_t evt; /**< The pending event. */
ble_db_discovery_evt_handler_t evt_handler; /**< The event handler which should be called to raise this event. */
} m_pending_user_evts[DB_DISCOVERY_MAX_USERS];
static ble_db_discovery_evt_handler_t m_evt_handler;
static uint32_t m_pending_usr_evt_index; /**< The index to the pending user event array, pointing to the last added pending user event. */
static uint32_t m_num_of_handlers_reg; /**< The number of handlers registered with the DB Discovery module. */
static bool m_initialized = false; /**< This variable Indicates if the module is initialized or not. */
#define MODULE_INITIALIZED (m_initialized == true)
#include "sdk_macros.h"
/**@brief Function for fetching the event handler provided by a registered application module.
*
* @param[in] srv_uuid UUID of the service.
*
* @retval evt_handler Event handler of the module, registered for the given service UUID.
* @retval NULL If no event handler is found.
*/
static ble_db_discovery_evt_handler_t registered_handler_get(const ble_uuid_t * const p_srv_uuid)
{
uint32_t i;
for (i = 0; i < m_num_of_handlers_reg; i++)
{
if (BLE_UUID_EQ(&(m_registered_handlers[i]), p_srv_uuid))
{
return (m_evt_handler);
}
}
return NULL;
}
/**@brief Function for storing the event handler provided by a registered application module.
*
* @param[in] p_srv_uuid The UUID of the service.
* @param[in] p_evt_handler The event handler provided by the application.
*
* @retval NRF_SUCCESS If the handler was stored or already present in the list.
* @retval NRF_ERROR_NO_MEM If there is no space left to store the handler.
*/
static uint32_t registered_handler_set(const ble_uuid_t * const p_srv_uuid,
ble_db_discovery_evt_handler_t p_evt_handler)
{
if (registered_handler_get(p_srv_uuid) != NULL)
{
return NRF_SUCCESS;
}
if (m_num_of_handlers_reg < DB_DISCOVERY_MAX_USERS)
{
m_registered_handlers[m_num_of_handlers_reg] = *p_srv_uuid;
m_num_of_handlers_reg++;
return NRF_SUCCESS;
}
else
{
return NRF_ERROR_NO_MEM;
}
}
/**@brief Function for sending all pending discovery events to the corresponding user modules.
*/
static void pending_user_evts_send(void)
{
uint32_t i = 0;
for (i = 0; i < m_num_of_handlers_reg; i++)
{
// Pass the event to the corresponding event handler.
m_pending_user_evts[i].evt_handler(&(m_pending_user_evts[i].evt));
}
m_pending_usr_evt_index = 0;
}
/**@brief Function for indicating error to the application.
*
* @details This function will fetch the event handler based on the UUID of the service being
* discovered. (The event handler is registered by the application beforehand).
* The error code is added to the pending events together with the event handler.
* If no event handler was found, then this function will do nothing.
*
* @param[in] p_db_discovery Pointer to the DB discovery structure.
* @param[in] err_code Error code that should be provided to the application.
* @param[in] conn_handle Connection Handle.
*
*/
static void discovery_error_evt_trigger(ble_db_discovery_t * const p_db_discovery,
uint32_t err_code,
uint16_t const conn_handle)
{
ble_db_discovery_evt_handler_t p_evt_handler;
ble_gatt_db_srv_t * p_srv_being_discovered;
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
p_evt_handler = registered_handler_get(&(p_srv_being_discovered->srv_uuid));
if (p_evt_handler != NULL)
{
ble_db_discovery_evt_t evt;
evt.conn_handle = conn_handle;
evt.evt_type = BLE_DB_DISCOVERY_ERROR;
evt.params.err_code = err_code;
p_evt_handler(&evt);
}
}
/**@brief Function for triggering a Discovery Complete or Service Not Found event to the
* application.
*
* @details This function will fetch the event handler based on the UUID of the service being
* discovered. (The event handler is registered by the application beforehand).
* It then triggers an event indicating the completion of the service discovery.
* If no event handler was found, then this function will do nothing.
*
* @param[in] p_db_discovery Pointer to the DB discovery structure.
* @param[in] is_srv_found Variable to indicate if the service was found at the peer.
* @param[in] conn_handle Connection Handle.
*/
static void discovery_complete_evt_trigger(ble_db_discovery_t * const p_db_discovery,
bool is_srv_found,
uint16_t const conn_handle)
{
ble_db_discovery_evt_handler_t p_evt_handler;
ble_gatt_db_srv_t * p_srv_being_discovered;
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
p_evt_handler = registered_handler_get(&(p_srv_being_discovered->srv_uuid));
if (p_evt_handler != NULL)
{
if (m_pending_usr_evt_index < DB_DISCOVERY_MAX_USERS)
{
// Insert an event into the pending event list.
m_pending_user_evts[m_pending_usr_evt_index].evt.conn_handle = conn_handle;
m_pending_user_evts[m_pending_usr_evt_index].evt.params.discovered_db =
*p_srv_being_discovered;
if (is_srv_found)
{
m_pending_user_evts[m_pending_usr_evt_index].evt.evt_type =
BLE_DB_DISCOVERY_COMPLETE;
}
else
{
m_pending_user_evts[m_pending_usr_evt_index].evt.evt_type =
BLE_DB_DISCOVERY_SRV_NOT_FOUND;
}
m_pending_user_evts[m_pending_usr_evt_index].evt_handler = p_evt_handler;
m_pending_usr_evt_index++;
if (m_pending_usr_evt_index == m_num_of_handlers_reg)
{
// All registered modules have pending events. Send all pending events to the user
// modules.
pending_user_evts_send();
}
else
{
// Too many events pending. Do nothing. (Ideally this should not happen.)
}
}
}
}
/**@brief Function for handling service discovery completion.
*
* @details This function will be used to determine if there are more services to be discovered,
* and if so, initiate the discovery of the next service.
*
* @param[in] p_db_discovery Pointer to the DB Discovery Structure.
* @param[in] conn_handle Connection Handle.
*/
static void on_srv_disc_completion(ble_db_discovery_t * p_db_discovery,
uint16_t const conn_handle)
{
p_db_discovery->discoveries_count++;
// Check if more services need to be discovered.
if (p_db_discovery->discoveries_count < m_num_of_handlers_reg)
{
// Reset the current characteristic index since a new service discovery is about to start.
p_db_discovery->curr_char_ind = 0;
// Initiate discovery of the next service.
p_db_discovery->curr_srv_ind++;
ble_gatt_db_srv_t * p_srv_being_discovered;
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
p_srv_being_discovered->srv_uuid = m_registered_handlers[p_db_discovery->curr_srv_ind];
// Reset the characteristic count in the current service to zero since a new service
// discovery is about to start.
p_srv_being_discovered->char_count = 0;
DB_LOG("[DB]: Starting discovery of service with UUID 0x%x for Connection handle %d\r\n",
p_srv_being_discovered->srv_uuid.uuid, conn_handle);
uint32_t err_code;
err_code = sd_ble_gattc_primary_services_discover
(
conn_handle,
SRV_DISC_START_HANDLE,
&(p_srv_being_discovered->srv_uuid)
);
if (err_code != NRF_SUCCESS)
{
p_db_discovery->discovery_in_progress = false;
// Error with discovering the service.
// Indicate the error to the registered user application.
discovery_error_evt_trigger(p_db_discovery, err_code, conn_handle);
m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE;
m_pending_user_evts[0].evt.conn_handle = conn_handle;
// m_evt_handler(&m_pending_user_evts[0].evt);
return;
}
}
else
{
// No more service discovery is needed.
p_db_discovery->discovery_in_progress = false;
m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE;
m_pending_user_evts[0].evt.conn_handle = conn_handle;
//m_evt_handler(&m_pending_user_evts[0].evt);
}
}
/**@brief Function for finding out if a characteristic discovery should be performed after the
* last discovered characteristic.
*
* @details This function is used during the time of database discovery to find out if there is
* a need to do more characteristic discoveries. The value handles of the
* last discovered characteristic is compared with the end handle of the service.
* If the service handle is greater than one of the former characteristic handles,
* it means that a characteristic discovery is required.
*
* @param[in] p_db_discovery The pointer to the DB Discovery structure.
* @param[in] p_after_char The pointer to the last discovered characteristic.
*
* @retval True if a characteristic discovery is required.
* @retval False if a characteristic discovery is NOT required.
*/
static bool is_char_discovery_reqd(ble_db_discovery_t * const p_db_discovery,
ble_gattc_char_t * p_after_char)
{
if (
p_after_char->handle_value <
p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle
)
{
// Handle value of the characteristic being discovered is less than the end handle of
// the service being discovered. There is a possibility of more characteristics being
// present. Hence a characteristic discovery is required.
return true;
}
return false;
}
/**@brief Function to find out if a descriptor discovery is required.
*
* @details This function finds out if there is a possibility of existence of descriptors between
* current characteristic and the next characteristic. If so, this function will compute
* the handle range on which the descriptors may be present and will return it.
* If the current characteristic is the last known characteristic, then this function
* will use the service end handle to find out if the current characteristic can have
* descriptors.
*
* @param[in] p_db_discovery Pointer to the DB Discovery structure.
* @param[in] p_curr_char Pointer to the current characteristic.
* @param[in] p_next_char Pointer to the next characteristic. This should be NULL if the
* caller knows that there is no characteristic after the current
* characteristic at the peer.
* @param[out] p_handle_range Pointer to the handle range in which descriptors may exist at the
* the peer.
*
* @retval True If a descriptor discovery is required.
* @retval False If a descriptor discovery is NOT required.
*/
static bool is_desc_discovery_reqd(ble_db_discovery_t * p_db_discovery,
ble_gatt_db_char_t * p_curr_char,
ble_gatt_db_char_t * p_next_char,
ble_gattc_handle_range_t * p_handle_range)
{
if (p_next_char == NULL)
{
// Current characteristic is the last characteristic in the service. Check if the value
// handle of the current characteristic is equal to the service end handle.
if (
p_curr_char->characteristic.handle_value ==
p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle
)
{
// No descriptors can be present for the current characteristic. p_curr_char is the last
// characteristic with no descriptors.
return false;
}
p_handle_range->start_handle = p_curr_char->characteristic.handle_value + 1;
// Since the current characteristic is the last characteristic in the service, the end
// handle should be the end handle of the service.
p_handle_range->end_handle =
p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle;
return true;
}
// p_next_char != NULL. Check for existence of descriptors between the current and the next
// characteristic.
if ((p_curr_char->characteristic.handle_value + 1) == p_next_char->characteristic.handle_decl)
{
// No descriptors can exist between the two characteristic.
return false;
}
p_handle_range->start_handle = p_curr_char->characteristic.handle_value + 1;
p_handle_range->end_handle = p_next_char->characteristic.handle_decl - 1;
return true;
}
/**@brief Function for performing characteristic discovery.
*
* @param[in] p_db_discovery Pointer to the DB Discovery structure.
* @param[in] conn_handle Connection Handle.
*
* @return NRF_SUCCESS if the SoftDevice was successfully requested to perform the characteristic
* discovery. Otherwise an error code. This function returns the error code returned
* by the SoftDevice API @ref sd_ble_gattc_characteristics_discover.
*/
static uint32_t characteristics_discover(ble_db_discovery_t * const p_db_discovery,
uint16_t const conn_handle)
{
ble_gatt_db_srv_t * p_srv_being_discovered;
ble_gattc_handle_range_t handle_range;
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
if (p_db_discovery->curr_char_ind != 0)
{
// This is not the first characteristic being discovered. Hence the 'start handle' to be
// used must be computed using the handle_value of the previous characteristic.
ble_gattc_char_t * p_prev_char;
uint8_t prev_char_ind = p_db_discovery->curr_char_ind - 1;
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
p_prev_char = &(p_srv_being_discovered->charateristics[prev_char_ind].characteristic);
handle_range.start_handle = p_prev_char->handle_value + 1;
}
else
{
// This is the first characteristic of this service being discovered.
handle_range.start_handle = p_srv_being_discovered->handle_range.start_handle;
}
handle_range.end_handle = p_srv_being_discovered->handle_range.end_handle;
return sd_ble_gattc_characteristics_discover(conn_handle, &handle_range);
}
/**@brief Function for performing descriptor discovery, if required.
*
* @details This function will check if descriptor discovery is required and then perform it if
* needed. If no more descriptor discovery is required for the service, then the output
* parameter p_raise_discov_complete is set to true, indicating to the caller that a
* discovery complete event can be triggered to the application.
*
* @param[in] p_db_discovery Pointer to the DB Discovery structure.
* @param[out] p_raise_discov_complete The value pointed to by this pointer will be set to true if
* the Discovery Complete event can be triggered to the
* application.
* @param[in] conn_handle Connection Handle.
*
* @return NRF_SUCCESS if the SoftDevice was successfully requested to perform the descriptor
* discovery, or if no more descriptor discovery is required. Otherwise an error code.
* This function returns the error code returned by the SoftDevice API @ref
* sd_ble_gattc_descriptors_discover.
*/
static uint32_t descriptors_discover(ble_db_discovery_t * const p_db_discovery,
bool * p_raise_discov_complete,
uint16_t const conn_handle)
{
ble_gattc_handle_range_t handle_range;
ble_gatt_db_char_t * p_curr_char_being_discovered;
ble_gatt_db_srv_t * p_srv_being_discovered;
bool is_discovery_reqd = false;
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
p_curr_char_being_discovered =
&(p_srv_being_discovered->charateristics[p_db_discovery->curr_char_ind]);
if ((p_db_discovery->curr_char_ind + 1) == p_srv_being_discovered->char_count)
{
// This is the last characteristic of this service.
is_discovery_reqd = is_desc_discovery_reqd(p_db_discovery,
p_curr_char_being_discovered,
NULL,
&handle_range);
}
else
{
uint8_t i;
ble_gatt_db_char_t * p_next_char;
for (i = p_db_discovery->curr_char_ind;
i < p_srv_being_discovered->char_count;
i++)
{
if (i == (p_srv_being_discovered->char_count - 1))
{
// The current characteristic is the last characteristic in the service.
p_next_char = NULL;
}
else
{
p_next_char = &(p_srv_being_discovered->charateristics[i + 1]);
}
// Check if it is possible for the current characteristic to have a descriptor.
if (is_desc_discovery_reqd(p_db_discovery,
p_curr_char_being_discovered,
p_next_char,
&handle_range))
{
is_discovery_reqd = true;
break;
}
else
{
// No descriptors can exist.
p_curr_char_being_discovered = p_next_char;
p_db_discovery->curr_char_ind++;
}
}
}
if (!is_discovery_reqd)
{
// No more descriptor discovery required. Discovery is complete.
// This informs the caller that a discovery complete event can be triggered.
*p_raise_discov_complete = true;
return NRF_SUCCESS;
}
*p_raise_discov_complete = false;
return sd_ble_gattc_descriptors_discover(conn_handle, &handle_range);
}
/**@brief Function for handling primary service discovery response.
*
* @details This function will handle the primary service discovery response and start the
* discovery of characteristics within that service.
*
* @param[in] p_db_discovery Pointer to the DB Discovery structure.
* @param[in] p_ble_gattc_evt Pointer to the GATT Client event.
*/
static void on_primary_srv_discovery_rsp(ble_db_discovery_t * const p_db_discovery,
const ble_gattc_evt_t * const p_ble_gattc_evt)
{
ble_gatt_db_srv_t * p_srv_being_discovered;
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle)
{
return;
}
if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS)
{
uint32_t err_code;
const ble_gattc_evt_prim_srvc_disc_rsp_t * p_prim_srvc_disc_rsp_evt;
DB_LOG("Found service UUID 0x%x\r\n", p_srv_being_discovered->srv_uuid.uuid);
p_prim_srvc_disc_rsp_evt = &(p_ble_gattc_evt->params.prim_srvc_disc_rsp);
p_srv_being_discovered->srv_uuid = p_prim_srvc_disc_rsp_evt->services[0].uuid;
p_srv_being_discovered->handle_range = p_prim_srvc_disc_rsp_evt->services[0].handle_range;
err_code = characteristics_discover(p_db_discovery,
p_ble_gattc_evt->conn_handle);
if (err_code != NRF_SUCCESS)
{
p_db_discovery->discovery_in_progress = false;
// Error with discovering the service.
// Indicate the error to the registered user application.
discovery_error_evt_trigger(p_db_discovery,
err_code,
p_ble_gattc_evt->conn_handle);
m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE;
m_pending_user_evts[0].evt.conn_handle = p_ble_gattc_evt->conn_handle;
//m_evt_handler(&m_pending_user_evts[0].evt);
}
}
else
{
DB_LOG("Service UUID 0x%x Not found\r\n", p_srv_being_discovered->srv_uuid.uuid);
// Trigger Service Not Found event to the application.
discovery_complete_evt_trigger(p_db_discovery,
false,
p_ble_gattc_evt->conn_handle);
on_srv_disc_completion(p_db_discovery,
p_ble_gattc_evt->conn_handle);
}
}
/**@brief Function for handling characteristic discovery response.
*
* @param[in] p_db_discovery Pointer to the DB Discovery structure.
* @param[in] p_ble_gattc_evt Pointer to the GATT Client event.
*/
static void on_characteristic_discovery_rsp(ble_db_discovery_t * const p_db_discovery,
const ble_gattc_evt_t * const p_ble_gattc_evt)
{
uint32_t err_code;
ble_gatt_db_srv_t * p_srv_being_discovered;
bool perform_desc_discov = false;
if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle)
{
return;
}
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS)
{
const ble_gattc_evt_char_disc_rsp_t * p_char_disc_rsp_evt;
p_char_disc_rsp_evt = &(p_ble_gattc_evt->params.char_disc_rsp);
// Find out the number of characteristics that were previously discovered (in earlier
// characteristic discovery responses, if any).
uint8_t num_chars_prev_disc = p_srv_being_discovered->char_count;
// Find out the number of characteristics that are currently discovered (in the
// characteristic discovery response being handled).
uint8_t num_chars_curr_disc = p_char_disc_rsp_evt->count;
// Check if the total number of discovered characteristics are supported by this module.
if ((num_chars_prev_disc + num_chars_curr_disc) <= BLE_GATT_DB_MAX_CHARS)
{
// Update the characteristics count.
p_srv_being_discovered->char_count += num_chars_curr_disc;
}
else
{
// The number of characteristics discovered at the peer is more than the supported
// maximum. This module will store only the characteristics found up to this point.
p_srv_being_discovered->char_count = BLE_GATT_DB_MAX_CHARS;
}
uint32_t i;
uint32_t j;
for (i = num_chars_prev_disc, j = 0; i < p_srv_being_discovered->char_count; i++, j++)
{
p_srv_being_discovered->charateristics[i].characteristic =
p_char_disc_rsp_evt->chars[j];
p_srv_being_discovered->charateristics[i].cccd_handle = BLE_GATT_HANDLE_INVALID;
}
ble_gattc_char_t * p_last_known_char;
p_last_known_char = &(p_srv_being_discovered->charateristics[i - 1].characteristic);
// If no more characteristic discovery is required, or if the maximum number of supported
// characteristic per service has been reached, descriptor discovery will be performed.
if (
!is_char_discovery_reqd(p_db_discovery, p_last_known_char) ||
(p_srv_being_discovered->char_count == BLE_GATT_DB_MAX_CHARS)
)
{
perform_desc_discov = true;
}
else
{
// Update the current characteristic index.
p_db_discovery->curr_char_ind = p_srv_being_discovered->char_count;
// Perform another round of characteristic discovery.
err_code = characteristics_discover(p_db_discovery,
p_ble_gattc_evt->conn_handle);
if (err_code != NRF_SUCCESS)
{
p_db_discovery->discovery_in_progress = false;
discovery_error_evt_trigger(p_db_discovery,
err_code,
p_ble_gattc_evt->conn_handle);
m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE;
m_pending_user_evts[0].evt.conn_handle = p_ble_gattc_evt->conn_handle;
//m_evt_handler(&m_pending_user_evts[0].evt);
return;
}
}
}
else
{
// The previous characteristic discovery resulted in no characteristics.
// descriptor discovery should be performed.
perform_desc_discov = true;
}
if (perform_desc_discov)
{
bool raise_discov_complete;
p_db_discovery->curr_char_ind = 0;
err_code = descriptors_discover(p_db_discovery,
&raise_discov_complete,
p_ble_gattc_evt->conn_handle);
if (err_code != NRF_SUCCESS)
{
p_db_discovery->discovery_in_progress = false;
discovery_error_evt_trigger(p_db_discovery,
err_code,
p_ble_gattc_evt->conn_handle);
m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE;
m_pending_user_evts[0].evt.conn_handle = p_ble_gattc_evt->conn_handle;
//m_evt_handler(&m_pending_user_evts[0].evt);
return;
}
if (raise_discov_complete)
{
// No more characteristics and descriptors need to be discovered. Discovery is complete.
// Send a discovery complete event to the user application.
DB_LOG("[DB]: Discovery of service with UUID 0x%x completed with success for Connection"
" handle %d\r\n", p_srv_being_discovered->srv_uuid.uuid,
p_ble_gattc_evt->conn_handle);
discovery_complete_evt_trigger(p_db_discovery,
true,
p_ble_gattc_evt->conn_handle);
on_srv_disc_completion(p_db_discovery,
p_ble_gattc_evt->conn_handle);
}
}
}
/**@brief Function for handling descriptor discovery response.
*
* @param[in] p_db_discovery Pointer to the DB Discovery structure.
* @param[in] p_ble_gattc_evt Pointer to the GATT Client event.
*/
static void on_descriptor_discovery_rsp(ble_db_discovery_t * const p_db_discovery,
const ble_gattc_evt_t * const p_ble_gattc_evt)
{
const ble_gattc_evt_desc_disc_rsp_t * p_desc_disc_rsp_evt;
ble_gatt_db_srv_t * p_srv_being_discovered;
if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle)
{
return;
}
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
p_desc_disc_rsp_evt = &(p_ble_gattc_evt->params.desc_disc_rsp);
ble_gatt_db_char_t * p_char_being_discovered =
&(p_srv_being_discovered->charateristics[p_db_discovery->curr_char_ind]);
if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS)
{
// The descriptor was found at the peer.
// If the descriptor was a CCCD, then the cccd_handle needs to be populated.
uint32_t i;
// Loop through all the descriptors to find the CCCD.
for (i = 0; i < p_desc_disc_rsp_evt->count; i++)
{
if (
p_desc_disc_rsp_evt->descs[i].uuid.uuid ==
BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG
)
{
p_char_being_discovered->cccd_handle = p_desc_disc_rsp_evt->descs[i].handle;
break;
}
}
}
bool raise_discov_complete = false;
if ((p_db_discovery->curr_char_ind + 1) == p_srv_being_discovered->char_count)
{
// No more characteristics and descriptors need to be discovered. Discovery is complete.
// Send a discovery complete event to the user application.
raise_discov_complete = true;
}
else
{
// Begin discovery of descriptors for the next characteristic.
uint32_t err_code;
p_db_discovery->curr_char_ind++;
err_code = descriptors_discover(p_db_discovery,
&raise_discov_complete,
p_ble_gattc_evt->conn_handle);
if (err_code != NRF_SUCCESS)
{
p_db_discovery->discovery_in_progress = false;
// Error with discovering the service.
// Indicate the error to the registered user application.
discovery_error_evt_trigger(p_db_discovery,
err_code,
p_ble_gattc_evt->conn_handle);
m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE;
m_pending_user_evts[0].evt.conn_handle = p_ble_gattc_evt->conn_handle;
return;
}
}
if (raise_discov_complete)
{
DB_LOG("[DB]: Discovery of service with UUID 0x%x completed with success for Connection"
"handle %d\r\n", p_srv_being_discovered->srv_uuid.uuid,
p_ble_gattc_evt->conn_handle);
discovery_complete_evt_trigger(p_db_discovery,
true,
p_ble_gattc_evt->conn_handle);
on_srv_disc_completion(p_db_discovery,
p_ble_gattc_evt->conn_handle);
}
}
uint32_t ble_db_discovery_init(const ble_db_discovery_evt_handler_t evt_handler)
{
uint32_t err_code = NRF_SUCCESS;
VERIFY_PARAM_NOT_NULL(evt_handler);
m_num_of_handlers_reg = 0;
m_initialized = true;
m_pending_usr_evt_index = 0;
m_evt_handler = evt_handler;
return err_code;
}
uint32_t ble_db_discovery_close()
{
m_num_of_handlers_reg = 0;
m_initialized = false;
m_pending_usr_evt_index = 0;
return NRF_SUCCESS;
}
uint32_t ble_db_discovery_evt_register(const ble_uuid_t * const p_uuid)
{
VERIFY_PARAM_NOT_NULL(p_uuid);
VERIFY_MODULE_INITIALIZED();
return registered_handler_set(p_uuid, m_evt_handler);
}
uint32_t ble_db_discovery_start(ble_db_discovery_t * const p_db_discovery,
uint16_t conn_handle)
{
VERIFY_PARAM_NOT_NULL(p_db_discovery);
VERIFY_MODULE_INITIALIZED();
if (m_num_of_handlers_reg == 0)
{
// No user modules were registered. There are no services to discover.
return NRF_ERROR_INVALID_STATE;
}
if (p_db_discovery->discovery_in_progress)
{
return NRF_ERROR_BUSY;
}
p_db_discovery->conn_handle = conn_handle;
ble_gatt_db_srv_t * p_srv_being_discovered;
m_pending_usr_evt_index = 0;
p_db_discovery->discoveries_count = 0;
p_db_discovery->curr_srv_ind = 0;
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
p_srv_being_discovered->srv_uuid = m_registered_handlers[p_db_discovery->curr_srv_ind];
DB_LOG("[DB]: Starting discovery of service with UUID 0x%x for Connection handle %d\r\n",
p_srv_being_discovered->srv_uuid.uuid, conn_handle);
uint32_t err_code;
err_code = sd_ble_gattc_primary_services_discover(conn_handle,
SRV_DISC_START_HANDLE,
&(p_srv_being_discovered->srv_uuid));
VERIFY_SUCCESS(err_code);
p_db_discovery->discovery_in_progress = true;
return NRF_SUCCESS;
}
/**@brief Function for handling disconnected event.
*
* @param[in] p_db_discovery Pointer to the DB Discovery structure.
* @param[in] p_ble_gattc_evt Pointer to the GAP event.
*/
static void on_disconnected(ble_db_discovery_t * const p_db_discovery,
const ble_gap_evt_t * const p_evt)
{
if (p_evt->conn_handle == p_db_discovery->conn_handle)
{
p_db_discovery->discovery_in_progress = false;
}
}
void ble_db_discovery_on_ble_evt(ble_db_discovery_t * const p_db_discovery,
const ble_evt_t * const p_ble_evt)
{
VERIFY_PARAM_NOT_NULL_VOID(p_db_discovery);
VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt);
VERIFY_MODULE_INITIALIZED_VOID();
switch (p_ble_evt->header.evt_id)
{
case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
on_primary_srv_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt));
break;
case BLE_GATTC_EVT_CHAR_DISC_RSP:
on_characteristic_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt));
break;
case BLE_GATTC_EVT_DESC_DISC_RSP:
on_descriptor_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt));
break;
case BLE_GAP_EVT_DISCONNECTED:
on_disconnected(p_db_discovery, &(p_ble_evt->evt.gap_evt));
break;
default:
break;
}
}

View File

@ -1,208 +0,0 @@
/*
* Copyright (c) 2013 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**@file
*
* @defgroup ble_sdk_lib_db_discovery Database Discovery
* @{
* @ingroup ble_sdk_lib
* @brief Database discovery module.
*
* @details This module contains the APIs and types exposed by the DB Discovery module. These APIs
* and types can be used by the application to perform discovery of a service and its
* characteristics at the peer server. This module can also be used to discover the
* desired services in multiple remote devices.
*
* @warning The maximum number of characteristics per service that can be discovered by this module
* is determined by the number of characteristics in the service structure defined in
* db_disc_config.h. If the peer has more than the supported number of characteristics, then
* the first found will be discovered and any further characteristics will be ignored. No
* descriptors other than Client Characteristic Configuration Descriptors will be searched
* for at the peer.
*
* @note Presently only one instance of a Primary Service can be discovered by this module. If
* there are multiple instances of the service at the peer, only the first instance
* of it at the peer is fetched and returned to the application.
*
* @note The application must propagate BLE stack events to this module by calling
* ble_db_discovery_on_ble_evt().
*
*/
#ifndef BLE_DB_DISCOVERY_H__
#define BLE_DB_DISCOVERY_H__
#include <stdint.h>
#include "nrf_ble_gattc.h"
#include "nrf_ble.h"
#include "nrf_error.h"
#include "ble_srv_common.h"
#include "ble_gatt_db.h"
#define BLE_DB_DISCOVERY_MAX_SRV 6 /**< Maximum number of services supported by this module. This also indicates the maximum number of users allowed to be registered to this module. (one user per service). */
/**@brief Type of the DB Discovery event.
*/
typedef enum
{
BLE_DB_DISCOVERY_COMPLETE, /**< Event indicating that the GATT Database discovery is complete. */
BLE_DB_DISCOVERY_ERROR, /**< Event indicating that an internal error has occurred in the DB Discovery module. This could typically be because of the SoftDevice API returning an error code during the DB discover.*/
BLE_DB_DISCOVERY_SRV_NOT_FOUND, /**< Event indicating that the service was not found at the peer.*/
BLE_DB_DISCOVERY_AVAILABLE /**< Event indicating that the DB discovery module is available.*/
} ble_db_discovery_evt_type_t;
/**@brief Structure for holding the information related to the GATT database at the server.
*
* @details This module identifies a remote database. Use one instance of this structure per
* connection.
*
* @warning This structure must be zero-initialized.
*/
typedef struct
{
ble_gatt_db_srv_t services[BLE_DB_DISCOVERY_MAX_SRV]; /**< Information related to the current service being discovered. This is intended for internal use during service discovery.*/
uint8_t srv_count; /**< Number of services at the peers GATT database.*/
uint8_t curr_char_ind; /**< Index of the current characteristic being discovered. This is intended for internal use during service discovery.*/
uint8_t curr_srv_ind; /**< Index of the current service being discovered. This is intended for internal use during service discovery.*/
bool discovery_in_progress; /**< Variable to indicate if there is a service discovery in progress. */
uint8_t discoveries_count; /**< Number of service discoveries made, both successful and unsuccessful. */
uint16_t conn_handle; /**< Connection handle on which the discovery is started*/
} ble_db_discovery_t;
/**@brief Structure containing the event from the DB discovery module to the application.
*/
typedef struct
{
ble_db_discovery_evt_type_t evt_type; /**< Type of event. */
uint16_t conn_handle; /**< Handle of the connection for which this event has occurred. */
union
{
ble_gatt_db_srv_t discovered_db; /**< Structure containing the information about the GATT Database at the server. This will be filled when the event type is @ref BLE_DB_DISCOVERY_COMPLETE.*/
uint32_t err_code; /**< nRF Error code indicating the type of error which occurred in the DB Discovery module. This will be filled when the event type is @ref BLE_DB_DISCOVERY_ERROR. */
} params;
} ble_db_discovery_evt_t;
/**@brief DB Discovery event handler type. */
typedef void (* ble_db_discovery_evt_handler_t)(ble_db_discovery_evt_t * p_evt);
/**@brief Function for initializing the DB Discovery module.
*
* @param[in] evt_handler Event handler to be called by the DB discovery module when any event
* related to discovery of the registered service occurs.
*
* @retval NRF_SUCCESS On successful initialization.
* @retval NRF_ERROR_NULL If the handler was NULL.
*/
uint32_t ble_db_discovery_init(ble_db_discovery_evt_handler_t evt_handler);
/**@brief Function for closing the DB Discovery module.
*
* @details This function will clear up any internal variables and states maintained by the
* module. To re-use the module after calling this function, the function @ref
* ble_db_discovery_init must be called again.
*
* @retval NRF_SUCCESS Operation success.
*/
uint32_t ble_db_discovery_close(void);
/**@brief Function for registering with the DB Discovery module.
*
* @details The application can use this function to inform which service it is interested in
* discovering at the server.
*
* @param[in] p_uuid Pointer to the UUID of the service to be discovered at the server.
*
* @note The total number of services that can be discovered by this module is @ref
* BLE_DB_DISCOVERY_MAX_SRV. This effectively means that the maximum number of
* registrations possible is equal to the @ref BLE_DB_DISCOVERY_MAX_SRV.
*
* @retval NRF_SUCCESS Operation success.
* @retval NRF_ERROR_NULL When a NULL pointer is passed as input.
* @retval NRF_ERROR_INVALID_STATE If this function is called without calling the
* @ref ble_db_discovery_init.
* @retval NRF_ERROR_NO_MEM The maximum number of registrations allowed by this module
* has been reached.
*/
uint32_t ble_db_discovery_evt_register(const ble_uuid_t * const p_uuid);
/**@brief Function for starting the discovery of the GATT database at the server.
*
* @warning p_db_discovery structure must be zero-initialized.
*
* @param[out] p_db_discovery Pointer to the DB Discovery structure.
* @param[in] conn_handle The handle of the connection for which the discovery should be
* started.
*
* @retval NRF_SUCCESS Operation success.
* @retval NRF_ERROR_NULL When a NULL pointer is passed as input.
* @retval NRF_ERROR_INVALID_STATE If this function is called without calling the
* @ref ble_db_discovery_init, or without calling
* @ref ble_db_discovery_evt_register.
* @retval NRF_ERROR_BUSY If a discovery is already in progress for the current
* connection.
*
* @return This API propagates the error code returned by the
* SoftDevice API @ref sd_ble_gattc_primary_services_discover.
*/
uint32_t ble_db_discovery_start(ble_db_discovery_t * const p_db_discovery,
uint16_t conn_handle);
/**@brief Function for handling the Application's BLE Stack events.
*
* @param[in,out] p_db_discovery Pointer to the DB Discovery structure.
* @param[in] p_ble_evt Pointer to the BLE event received.
*/
void ble_db_discovery_on_ble_evt(ble_db_discovery_t * const p_db_discovery,
const ble_evt_t * const p_ble_evt);
#endif // BLE_DB_DISCOVERY_H__
/** @} */

View File

@ -1,82 +0,0 @@
/*
* Copyright (c) 2013 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ble_debug_assert_handler.h"
#include <string.h>
#include "nrf.h"
#include "ble_error_log.h"
#include "nordic_common.h"
#define MAX_LENGTH_FILENAME 128 /**< Max length of filename to copy for the debug error handlier. */
// WARNING - DO NOT USE THIS FUNCTION IN END PRODUCT. - WARNING
// WARNING - FOR DEBUG PURPOSES ONLY. - WARNING
void ble_debug_assert_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name)
{
// Copying parameters to static variables because parameters may not be accessible in debugger.
static volatile uint8_t s_file_name[MAX_LENGTH_FILENAME];
static volatile uint16_t s_line_num;
static volatile uint32_t s_error_code;
strncpy((char *)s_file_name, (const char *)p_file_name, MAX_LENGTH_FILENAME - 1);
s_file_name[MAX_LENGTH_FILENAME - 1] = '\0';
s_line_num = line_num;
s_error_code = error_code;
UNUSED_VARIABLE(s_file_name);
UNUSED_VARIABLE(s_line_num);
UNUSED_VARIABLE(s_error_code);
// WARNING: The PRIMASK register is set to disable ALL interrups during writing the error log.
//
// Do not use __disable_irq() in normal operation.
__disable_irq();
// This function will write error code, filename, and line number to the flash.
// In addition, the Cortex-M0 stack memory will also be written to the flash.
//(void) ble_error_log_write(error_code, p_file_name, line_num);
// For debug purposes, this function never returns.
// Attach a debugger for tracing the error cause.
for (;;)
{
// Do nothing.
}
}

View File

@ -1,78 +0,0 @@
/*
* Copyright (c) 2013 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** @file
*
* @defgroup ble_debug_assert_handler Assert handler for debug purposes
* @{
* @ingroup ble_sdk_lib
* @brief Module for handling of assert during application development when debugging.
*
* @details This module may be used during development of an application to facilitate debugging.
* It contains a function to write file name, line number and the Stack Memory to flash.
* This module is ONLY for debugging purposes and must never be used in final product.
*
*/
#ifndef BLE_DEBUG_ASSERT_HANDLER_H__
#define BLE_DEBUG_ASSERT_HANDLER_H__
#include <stdint.h>
/**@brief Function for handling the Debug assert, which can be called from an error handler.
* To be used only for debugging purposes.
*
*@details This code will copy the filename and line number into local variables for them to always
* be accessible in Keil debugger. The function will also write the ARM Cortex-M0 stack
* memory into flash where it can be retrieved and manually un-winded in order to
* back-trace the location where the error ocured.<br>
* @warning <b>ALL INTERRUPTS WILL BE DISABLED.</b>
*
* @note This function will never return but loop forever for debug purposes.
*
* @param[in] error_code Error code supplied to the handler.
* @param[in] line_num Line number where the original handler is called.
* @param[in] p_file_name Pointer to the file name.
*/
void ble_debug_assert_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name);
#endif /* BLE_DEBUG_ASSERT_HANDLER_H__ */
/** @} */

View File

@ -1,670 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ble_dtm.h"
#include <stdbool.h>
#include <string.h>
#include "nrf.h"
#define DTM_HEADER_OFFSET 0 /**< Index where the header of the pdu is located. */
#define DTM_HEADER_SIZE 2 /**< Size of PDU header. */
#define DTM_PAYLOAD_MAX_SIZE 37 /**< Maximum payload size allowed during dtm execution. */
#define DTM_LENGTH_OFFSET (DTM_HEADER_OFFSET + 1) /**< Index where the length of the payload is encoded. */
#define DTM_PDU_MAX_MEMORY_SIZE (DTM_HEADER_SIZE + DTM_PAYLOAD_MAX_SIZE) /**< Maximum PDU size allowed during dtm execution. */
/**@details The UART poll cycle in micro seconds.
* Baud rate of 19200 bits / second, and 8 data bits, 1 start/stop bit, no flow control,
* give the time to transmit a byte: 10 bits * 1/19200 = approx: 520 us.
*
* To ensure no loss of bytes, the UART should be polled every 260 us.
*
* @note If UART bit rate is changed, this value should be recalculated as well.
*/
#define UART_POLL_CYCLE 260
#define RX_MODE true /**< Constant defining RX mode for radio during dtm test. */
#define TX_MODE false /**< Constant defining TX mode for radio during dtm test. */
#define PHYS_CH_MAX 39 /**< Maximum number of valid channels in BLE. */
// Values that for now are "constants" - they could be configured by a function setting them,
// but most of these are set by the BLE DTM standard, so changing them is not relevant.
#define RFPHY_TEST_0X0F_REF_PATTERN 0x0f /**< RF-PHY test packet patterns, for the repeated octet packets. */
#define RFPHY_TEST_0X55_REF_PATTERN 0x55 /**< RF-PHY test packet patterns, for the repeated octet packets. */
#define PRBS9_CONTENT {0xff, 0xc1, 0xfb, 0xe8, 0x4c, 0x90, 0x72, 0x8b, \
0xe7, 0xb3, 0x51, 0x89, 0x63, 0xab, 0x23, 0x23, \
0x2, 0x84, 0x18, 0x72, 0xaa, 0x61, 0x2f, 0x3b, \
0x51, 0xa8, 0xe5, 0x37, 0x49, 0xfb, 0xc9, 0xca, \
0xc, 0x18, 0x53, 0x2c, 0xfd} /**< The PRBS9 sequence used as packet payload. */
/**@brief Structure holding the PDU used for transmitting/receiving a PDU.
*/
typedef struct
{
uint8_t content[DTM_HEADER_SIZE + DTM_PAYLOAD_MAX_SIZE]; /**< PDU packet content. */
} pdu_type_t;
/**@brief States used for the DTM test implementation.
*/
typedef enum
{
STATE_UNINITIALIZED, /**< The DTM is uninitialized. */
STATE_IDLE, /**< State when system has just initialized, or current test has completed. */
STATE_TRANSMITTER_TEST, /**< State used when a DTM Transmission test is running. */
STATE_CARRIER_TEST, /**< State used when a DTM Carrier test is running (Vendor specific test). */
STATE_RECEIVER_TEST /**< State used when a DTM Receive test is running. */
} state_t;
// Internal variables set as side effects of commands or events.
static state_t m_state = STATE_UNINITIALIZED; /**< Current machine state. */
static uint16_t m_rx_pkt_count; /**< Number of valid packets received. */
static pdu_type_t m_pdu; /**< PDU to be sent. */
static uint16_t m_event; /**< current command status - initially "ok", may be set if error detected, or to packet count. */
static bool m_new_event; /**< Command has been processed - number of not yet reported event bytes. */
static uint8_t m_packet_length; /**< Payload length of transmitted PDU, bits 2:7 of 16-bit dtm command. */
static dtm_pkt_type_t m_packet_type; /**< Bits 0..1 of 16-bit transmit command, or 0xFFFFFFFF. */
static dtm_freq_t m_phys_ch; /**< 0..39 physical channel number (base 2402 MHz, Interval 2 MHz), bits 8:13 of 16-bit dtm command. */
static uint32_t m_current_time = 0; /**< Counter for interrupts from timer to ensure that the 2 bytes forming a DTM command are received within the time window. */
// Nordic specific configuration values (not defined by BLE standard).
// Definition of initial values found in ble_dtm.h
static int32_t m_tx_power = DEFAULT_TX_POWER; /**< TX power for transmission test, default to maximum value (+4 dBm). */
static NRF_TIMER_Type * mp_timer = DEFAULT_TIMER; /**< Timer to be used. */
static IRQn_Type m_timer_irq = DEFAULT_TIMER_IRQn; /**< which interrupt line to clear on every timeout */
static uint8_t const m_prbs_content[] = PRBS9_CONTENT; /**< Pseudo-random bit sequence defined by the BLE standard. */
static uint8_t m_packetHeaderLFlen = 8; /**< Length of length field in packet Header (in bits). */
static uint8_t m_packetHeaderS0len = 1; /**< Length of S0 field in packet Header (in bytes). */
static uint8_t m_packetHeaderS1len = 0; /**< Length of S1 field in packet Header (in bits). */
static uint8_t m_crcConfSkipAddr = 1; /**< Leave packet address field out of CRC calculation. */
static uint8_t m_static_length = 0; /**< Number of bytes sent in addition to the var.length payload. */
static uint32_t m_balen = 3; /**< Base address length in bytes. */
static uint32_t m_endian = RADIO_PCNF1_ENDIAN_Little; /**< On air endianess of packet, this applies to the S0, LENGTH, S1 and the PAYLOAD fields. */
static uint32_t m_whitening = RADIO_PCNF1_WHITEEN_Disabled; /**< Whitening disabled. */
static uint8_t m_crcLength = RADIO_CRCCNF_LEN_Three; /**< CRC Length (in bytes). */
static uint32_t m_address = 0x71764129; /**< Address. */
static uint32_t m_crc_poly = 0x0000065B; /**< CRC polynomial. */
static uint32_t m_crc_init = 0x00555555; /**< Initial value for CRC calculation. */
static uint8_t m_radio_mode = RADIO_MODE_MODE_Ble_1Mbit; /**< nRF51 specific radio mode vale. */
static uint32_t m_txIntervaluS = 625; /**< Time between start of Tx packets (in uS). */
/**@brief Function for verifying that a received PDU has the expected structure and content.
*/
static bool check_pdu(void)
{
uint8_t k; // Byte pointer for running through PDU payload
uint8_t pattern; // Repeating octet value in payload
dtm_pkt_type_t pdu_packet_type; // Note: PDU packet type is a 4-bit field in HCI, but 2 bits in BLE DTM
uint8_t length;
pdu_packet_type = (dtm_pkt_type_t)(m_pdu.content[DTM_HEADER_OFFSET] & 0x0F);
length = m_pdu.content[DTM_LENGTH_OFFSET];
if ((pdu_packet_type > (dtm_pkt_type_t)PACKET_TYPE_MAX) || (length > DTM_PAYLOAD_MAX_SIZE))
{
return false;
}
if (pdu_packet_type == DTM_PKT_PRBS9)
{
// Payload does not consist of one repeated octet; must compare ir with entire block into
return (memcmp(m_pdu.content+DTM_HEADER_SIZE, m_prbs_content, length) == 0);
}
if (pdu_packet_type == DTM_PKT_0X0F)
{
pattern = RFPHY_TEST_0X0F_REF_PATTERN;
}
else
{
pattern = RFPHY_TEST_0X55_REF_PATTERN;
}
for (k = 0; k < length; k++)
{
// Check repeated pattern filling the PDU payload
if (m_pdu.content[k + 2] != pattern)
{
return false;
}
}
return true;
}
/**@brief Function for turning off the radio after a test.
* Also called after test done, to be ready for next test.
*/
static void radio_reset(void)
{
NRF_PPI->CHENCLR = PPI_CHENCLR_CH0_Msk | PPI_CHENCLR_CH1_Msk;
NRF_RADIO->SHORTS = 0;
NRF_RADIO->EVENTS_DISABLED = 0;
NRF_RADIO->TASKS_DISABLE = 1;
while (NRF_RADIO->EVENTS_DISABLED == 0)
{
// Do nothing
}
NRF_RADIO->EVENTS_DISABLED = 0;
NRF_RADIO->TASKS_RXEN = 0;
NRF_RADIO->TASKS_TXEN = 0;
m_rx_pkt_count = 0;
}
/**@brief Function for initializing the radio for DTM.
*/
static uint32_t radio_init(void)
{
#ifdef NRF51
// Handle BLE Radio tuning parameters from production for DTM if required.
// Only needed for DTM without SoftDevice, as the SoftDevice normally handles this.
// PCN-083.
if ( ((NRF_FICR->OVERRIDEEN) & FICR_OVERRIDEEN_BLE_1MBIT_Msk) == FICR_OVERRIDEEN_BLE_1MBIT_Override)
{
NRF_RADIO->OVERRIDE0 = NRF_FICR->BLE_1MBIT[0];
NRF_RADIO->OVERRIDE1 = NRF_FICR->BLE_1MBIT[1];
NRF_RADIO->OVERRIDE2 = NRF_FICR->BLE_1MBIT[2];
NRF_RADIO->OVERRIDE3 = NRF_FICR->BLE_1MBIT[3];
NRF_RADIO->OVERRIDE4 = NRF_FICR->BLE_1MBIT[4];
}
#endif // NRF51
// Initializing code below is quite generic - for BLE, the values are fixed, and expressions
// are constant. Non-constant values are essentially set in radio_prepare().
if (((m_tx_power & 0x03) != 0) || // tx_power should be a multiple of 4
((m_tx_power & 0xffffff00) != 0) || // Upper 24 bits are required to be zeroed
((int8_t)m_tx_power > 4) || // Max tx_power is +4 dBm
((int8_t)(m_tx_power & 0xff) < -40) || // Min tx_power is -40 dBm
(m_radio_mode > RADIO_MODE_MODE_Ble_1Mbit) // Values 0-2: Proprietary mode, 3 (last valid): BLE
)
{
return DTM_ERROR_ILLEGAL_CONFIGURATION;
}
// Turn off radio before configuring it
radio_reset();
NRF_RADIO->TXPOWER = m_tx_power;
NRF_RADIO->MODE = m_radio_mode << RADIO_MODE_MODE_Pos;
// Set the access address, address0/prefix0 used for both Rx and Tx address
NRF_RADIO->PREFIX0 &= ~RADIO_PREFIX0_AP0_Msk;
NRF_RADIO->PREFIX0 |= (m_address >> 24) & RADIO_PREFIX0_AP0_Msk;
NRF_RADIO->BASE0 = m_address << 8;
NRF_RADIO->RXADDRESSES = RADIO_RXADDRESSES_ADDR0_Enabled << RADIO_RXADDRESSES_ADDR0_Pos;
NRF_RADIO->TXADDRESS = (0x00 << RADIO_TXADDRESS_TXADDRESS_Pos) & RADIO_TXADDRESS_TXADDRESS_Msk;
// Configure CRC calculation
NRF_RADIO->CRCCNF = (m_crcConfSkipAddr << RADIO_CRCCNF_SKIP_ADDR_Pos) |
(m_crcLength << RADIO_CRCCNF_LEN_Pos);
NRF_RADIO->PCNF0 = (m_packetHeaderS1len << RADIO_PCNF0_S1LEN_Pos) |
(m_packetHeaderS0len << RADIO_PCNF0_S0LEN_Pos) |
(m_packetHeaderLFlen << RADIO_PCNF0_LFLEN_Pos);
NRF_RADIO->PCNF1 = (m_whitening << RADIO_PCNF1_WHITEEN_Pos) |
(m_endian << RADIO_PCNF1_ENDIAN_Pos) |
(m_balen << RADIO_PCNF1_BALEN_Pos) |
(m_static_length << RADIO_PCNF1_STATLEN_Pos) |
(DTM_PAYLOAD_MAX_SIZE << RADIO_PCNF1_MAXLEN_Pos);
return DTM_SUCCESS;
}
/**@brief Function for preparing the radio. At start of each test: Turn off RF, clear interrupt flags of RF, initialize the radio
* at given RF channel.
*
*@param[in] rx boolean indicating if radio should be prepared in rx mode (true) or tx mode.
*/
static void radio_prepare(bool rx)
{
#ifdef NRF51
NRF_RADIO->TEST = 0;
#elif defined(NRF52)
NRF_RADIO->MODECNF0 = (RADIO_MODECNF0_RU_Default << RADIO_MODECNF0_RU_Pos) |
(RADIO_MODECNF0_DTX_B1 << RADIO_MODECNF0_DTX_Pos);
#endif // NRF51 / NRF52
NRF_RADIO->CRCPOLY = m_crc_poly;
NRF_RADIO->CRCINIT = m_crc_init;
NRF_RADIO->FREQUENCY = (m_phys_ch << 1) + 2; // Actual frequency (MHz): 2400 + register value
NRF_RADIO->PACKETPTR = (uint32_t)&m_pdu; // Setting packet pointer will start the radio
NRF_RADIO->EVENTS_READY = 0;
NRF_RADIO->SHORTS = (1 << RADIO_SHORTS_READY_START_Pos) | // Shortcut between READY event and START task
(1 << RADIO_SHORTS_END_DISABLE_Pos); // Shortcut between END event and DISABLE task
if (rx)
{
NRF_RADIO->EVENTS_END = 0;
NRF_RADIO->TASKS_RXEN = 1; // shorts will start radio in RX mode when it is ready
}
else // tx
{
NRF_RADIO->TXPOWER = m_tx_power;
}
}
/**@brief Function for terminating the ongoing test (if any) and closing down the radio.
*/
static void dtm_test_done(void)
{
#ifdef NRF51
NRF_RADIO->TEST = 0;
#elif defined(NRF52)
NRF_RADIO->MODECNF0 = (RADIO_MODECNF0_RU_Default << RADIO_MODECNF0_RU_Pos) |
(RADIO_MODECNF0_DTX_B1 << RADIO_MODECNF0_DTX_Pos);
#endif // NRF51 / NRF52
NRF_PPI->CHENCLR = 0x01;
NRF_PPI->CH[0].EEP = 0; // Break connection from timer to radio to stop transmit loop
NRF_PPI->CH[0].TEP = 0;
radio_reset();
m_state = STATE_IDLE;
}
/**@brief Function for configuring the timer for 625us cycle time.
*/
static uint32_t timer_init(void)
{
// Use 16MHz from external crystal
// This could be customized for RC/Xtal, or even to use a 32 kHz crystal
NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
NRF_CLOCK->TASKS_HFCLKSTART = 1;
while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
{
// Do nothing while waiting for the clock to start
}
mp_timer->TASKS_STOP = 1; // Stop timer, if it was running
mp_timer->TASKS_CLEAR = 1;
mp_timer->MODE = TIMER_MODE_MODE_Timer; // Timer mode (not counter)
mp_timer->EVENTS_COMPARE[0] = 0; // clean up possible old events
mp_timer->EVENTS_COMPARE[1] = 0;
mp_timer->EVENTS_COMPARE[2] = 0;
mp_timer->EVENTS_COMPARE[3] = 0;
// Timer is polled, but enable the compare0 interrupt in order to wakeup from CPU sleep
mp_timer->INTENSET = TIMER_INTENSET_COMPARE0_Msk;
mp_timer->SHORTS = 1 << TIMER_SHORTS_COMPARE0_CLEAR_Pos; // Clear the count every time timer reaches the CCREG0 count
mp_timer->PRESCALER = 4; // Input clock is 16MHz, timer clock = 2 ^ prescale -> interval 1us
mp_timer->CC[0] = m_txIntervaluS; // 625uS with 1MHz clock to the timer
mp_timer->CC[1] = UART_POLL_CYCLE; // 260uS with 1MHz clock to the timer
mp_timer->TASKS_START = 1; // Start the timer - it will be running continuously
m_current_time = 0;
return DTM_SUCCESS;
}
/**@brief Function for handling vendor specific commands.
* Used when packet type is set to Vendor specific.
* The length field is used for encoding vendor specific command.
* The frequency field is used for encoding vendor specific options to the command.
*
* @param[in] vendor_cmd Vendor specific command to be executed.
* @param[in] vendor_option Vendor specific option to the vendor command.
*
* @return DTM_SUCCESS or one of the DTM_ERROR_ values
*/
static uint32_t dtm_vendor_specific_pkt(uint32_t vendor_cmd, dtm_freq_t vendor_option)
{
switch (vendor_cmd)
{
// nRFgo Studio uses CARRIER_TEST_STUDIO to indicate a continuous carrier without
// a modulated signal.
case CARRIER_TEST:
case CARRIER_TEST_STUDIO:
// Not a packet type, but used to indicate that a continuous carrier signal
// should be transmitted by the radio.
radio_prepare(TX_MODE);
#ifdef NRF51
NRF_RADIO->TEST = (RADIO_TEST_PLL_LOCK_Enabled << RADIO_TEST_PLL_LOCK_Pos) |
(RADIO_TEST_CONST_CARRIER_Enabled << RADIO_TEST_CONST_CARRIER_Pos);
#elif defined(NRF52)
NRF_RADIO->MODECNF0 = (RADIO_MODECNF0_RU_Default << RADIO_MODECNF0_RU_Pos) |
(RADIO_MODECNF0_DTX_B1 << RADIO_MODECNF0_DTX_Pos);
#endif // NRF51 / NRF52
// Shortcut between READY event and START task
NRF_RADIO->SHORTS = 1 << RADIO_SHORTS_READY_START_Pos;
// Shortcut will start radio in Tx mode when it is ready
NRF_RADIO->TASKS_TXEN = 1;
m_state = STATE_CARRIER_TEST;
break;
case SET_TX_POWER:
if (!dtm_set_txpower(vendor_option))
{
return DTM_ERROR_ILLEGAL_CONFIGURATION;
}
break;
case SELECT_TIMER:
if (!dtm_set_timer(vendor_option))
{
return DTM_ERROR_ILLEGAL_CONFIGURATION;
}
break;
}
// Event code is unchanged, successful
return DTM_SUCCESS;
}
uint32_t dtm_init(void)
{
if ((timer_init() != DTM_SUCCESS) || (radio_init() != DTM_SUCCESS))
{
return DTM_ERROR_ILLEGAL_CONFIGURATION;
}
m_new_event = false;
m_state = STATE_IDLE;
// Enable wake-up on event
SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
return DTM_SUCCESS;
}
uint32_t dtm_wait(void)
{
// Enable wake-up on event
SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
for (;;)
{
// Event may be the reception of a packet -
// handle radio first, to give it highest priority:
if (NRF_RADIO->EVENTS_END != 0)
{
NRF_RADIO->EVENTS_END = 0;
NVIC_ClearPendingIRQ(RADIO_IRQn);
if (m_state == STATE_RECEIVER_TEST)
{
NRF_RADIO->TASKS_RXEN = 1;
if ((NRF_RADIO->CRCSTATUS == 1) && check_pdu())
{
// Count the number of successfully received packets
m_rx_pkt_count++;
}
// Note that failing packets are simply ignored (CRC or contents error).
// Zero fill all pdu fields to avoid stray data
memset(&m_pdu, 0, DTM_PDU_MAX_MEMORY_SIZE);
}
// If no RECEIVER_TEST is running, ignore incoming packets (but do clear IRQ!)
}
// Check for timeouts:
if (mp_timer->EVENTS_COMPARE[0] != 0)
{
mp_timer->EVENTS_COMPARE[0] = 0;
}
else if (mp_timer->EVENTS_COMPARE[1] != 0)
{
// Reset timeout event flag for next iteration.
mp_timer->EVENTS_COMPARE[1] = 0;
NVIC_ClearPendingIRQ(m_timer_irq);
return ++m_current_time;
}
// Other events: No processing
}
}
uint32_t dtm_cmd(dtm_cmd_t cmd, dtm_freq_t freq, uint32_t length, dtm_pkt_type_t payload)
{
// Save specified packet in static variable for tx/rx functions to use.
// Note that BLE conformance testers always use full length packets.
m_packet_length = ((uint8_t)length & 0xFF);
m_packet_type = payload;
m_phys_ch = freq;
// Clean out any non-retrieved event that might linger from an earlier test
m_new_event = true;
// Set default event; any error will set it to LE_TEST_STATUS_EVENT_ERROR
m_event = LE_TEST_STATUS_EVENT_SUCCESS;
if (m_state == STATE_UNINITIALIZED)
{
// Application has not explicitly initialized DTM,
return DTM_ERROR_UNINITIALIZED;
}
if (cmd == LE_RESET)
{
// Note that timer will continue running after a reset
dtm_test_done();
return DTM_SUCCESS;
}
if (cmd == LE_TEST_END)
{
if (m_state == STATE_IDLE)
{
// Sequencing error - only rx or tx test may be ended!
m_event = LE_TEST_STATUS_EVENT_ERROR;
return DTM_ERROR_INVALID_STATE;
}
m_event = LE_PACKET_REPORTING_EVENT | m_rx_pkt_count;
dtm_test_done();
return DTM_SUCCESS;
}
if (m_state != STATE_IDLE)
{
// Sequencing error - only TEST_END/RESET are legal while test is running
// Note: State is unchanged; ongoing test not affected
m_event = LE_TEST_STATUS_EVENT_ERROR;
return DTM_ERROR_INVALID_STATE;
}
if (m_phys_ch > PHYS_CH_MAX)
{
// Parameter error
// Note: State is unchanged; ongoing test not affected
m_event = LE_TEST_STATUS_EVENT_ERROR;
return DTM_ERROR_ILLEGAL_CHANNEL;
}
m_rx_pkt_count = 0;
if (cmd == LE_RECEIVER_TEST)
{
// Zero fill all pdu fields to avoid stray data from earlier test run
memset(&m_pdu, 0, DTM_PDU_MAX_MEMORY_SIZE);
radio_prepare(RX_MODE); // Reinitialize "everything"; RF interrupts OFF
m_state = STATE_RECEIVER_TEST;
return DTM_SUCCESS;
}
if (cmd == LE_TRANSMITTER_TEST)
{
if (m_packet_length > DTM_PAYLOAD_MAX_SIZE)
{
// Parameter error
m_event = LE_TEST_STATUS_EVENT_ERROR;
return DTM_ERROR_ILLEGAL_LENGTH;
}
// Note that PDU uses 4 bits even though BLE DTM uses only 2 (the HCI SDU uses all 4)
m_pdu.content[DTM_HEADER_OFFSET] = ((uint8_t)m_packet_type & 0x0F);
m_pdu.content[DTM_LENGTH_OFFSET] = m_packet_length;
switch (m_packet_type)
{
case DTM_PKT_PRBS9:
// Non-repeated, must copy entire pattern to PDU
memcpy(m_pdu.content + DTM_HEADER_SIZE, m_prbs_content, length);
break;
case DTM_PKT_0X0F:
// Bit pattern 00001111 repeated
memset(m_pdu.content + DTM_HEADER_SIZE, RFPHY_TEST_0X0F_REF_PATTERN, length);
break;
case DTM_PKT_0X55:
// Bit pattern 01010101 repeated
memset(m_pdu.content + DTM_HEADER_SIZE, RFPHY_TEST_0X55_REF_PATTERN, length);
break;
case DTM_PKT_VENDORSPECIFIC:
// The length field is for indicating the vendor specific command to execute.
// The frequency field is used for vendor specific options to the command.
return dtm_vendor_specific_pkt(length, freq);
default:
// Parameter error
m_event = LE_TEST_STATUS_EVENT_ERROR;
return DTM_ERROR_ILLEGAL_CONFIGURATION;
}
// Initialize CRC value, set channel:
radio_prepare(TX_MODE);
// Configure PPI so that timer will activate radio every 625 us
NRF_PPI->CH[0].EEP = (uint32_t)&mp_timer->EVENTS_COMPARE[0];
NRF_PPI->CH[0].TEP = (uint32_t)&NRF_RADIO->TASKS_TXEN;
NRF_PPI->CHENSET = 0x01;
m_state = STATE_TRANSMITTER_TEST;
}
return DTM_SUCCESS;
}
bool dtm_event_get(dtm_event_t *p_dtm_event)
{
bool was_new = m_new_event;
// mark the current event as retrieved
m_new_event = false;
*p_dtm_event = m_event;
// return value indicates whether this value was already retrieved.
return was_new;
}
// =================================================================================================
// Configuration functions (only for parameters not definitely determined by the BLE DTM standard).
// These functions return true if successful, false if value could not be set
/**@brief Function for configuring the output power for transmitter test.
This function may be called directly, or through dtm_cmd() specifying
DTM_PKT_VENDORSPECIFIC as payload, SET_TX_POWER as length, and the dBm value as frequency.
*/
bool dtm_set_txpower(uint32_t new_tx_power)
{
// radio->TXPOWER register is 32 bits, low octet a signed value, upper 24 bits zeroed
int8_t new_power8 = (int8_t)(new_tx_power & 0xFF);
if (m_state > STATE_IDLE)
{
// radio must be idle to change the tx power
return false;
}
if ((new_power8 > 4) || (new_power8 < -40))
{
// Parameter outside valid range: nRF radio is restricted to the range -40 dBm to +4 dBm
return false;
}
if (new_tx_power & 0x03)
{
// Parameter error: The nRF51 radio requires settings that are a multiple of 4.
return false;
}
m_tx_power = new_tx_power;
return true;
}
/**@brief Function for selecting a timer resource.
* This function may be called directly, or through dtm_cmd() specifying
* DTM_PKT_VENDORSPECIFIC as payload, SELECT_TIMER as length, and the timer as freq
*
* @param[in] new_timer Timer id for the timer to use: 0, 1, or 2.
*
* @return true if the timer was successfully changed, false otherwise.
*/
bool dtm_set_timer(uint32_t new_timer)
{
if (m_state > STATE_IDLE)
{
return false;
}
if (new_timer == 0)
{
mp_timer = NRF_TIMER0;
m_timer_irq = TIMER0_IRQn;
}
else if (new_timer == 1)
{
mp_timer = NRF_TIMER1;
m_timer_irq = TIMER1_IRQn;
}
else if (new_timer == 2)
{
mp_timer = NRF_TIMER2;
m_timer_irq = TIMER2_IRQn;
}
else
{
// Parameter error: Only TIMER 0, 1, 2 provided by nRF51
return false;
}
// New timer has been selected:
return true;
}
/// @}

View File

@ -1,168 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** @file
*
* @defgroup ble_sdk_dtmlib_dtm DTM - Direct Test Mode
* @{
* @ingroup ble_sdk_lib
* @brief Module for testing RF/PHY using DTM commands.
*/
#ifndef BLE_DTM_H__
#define BLE_DTM_H__
#include <stdint.h>
#include <stdbool.h>
/**@brief Configuration parameters. */
#define DEFAULT_TX_POWER RADIO_TXPOWER_TXPOWER_0dBm /**< Default Transmission power using in the DTM module. */
#define DEFAULT_TIMER NRF_TIMER0 /**< Default timer used for timing. */
#define DEFAULT_TIMER_IRQn TIMER0_IRQn /**< IRQ used for timer. NOTE: MUST correspond to DEFAULT_TIMER. */
/**@brief BLE DTM command codes. */
typedef uint32_t dtm_cmd_t; /**< DTM command type. */
#define LE_RESET 0 /**< DTM command: Reset device. */
#define LE_RECEIVER_TEST 1 /**< DTM command: Start receive test. */
#define LE_TRANSMITTER_TEST 2 /**< DTM command: Start transmission test. */
#define LE_TEST_END 3 /**< DTM command: End test and send packet report. */
// Configuration options used as parameter 2
// when cmd == LE_TRANSMITTER_TEST and payload == DTM_PKT_VENDORSPECIFIC
// Configuration value, if any, is supplied in parameter 3
#define CARRIER_TEST 0 /**< Length=0 indicates a constant, unmodulated carrier until LE_TEST_END or LE_RESET */
#define CARRIER_TEST_STUDIO 1 /**< nRFgo Studio uses value 1 in length field, to indicate a constant, unmodulated carrier until LE_TEST_END or LE_RESET */
#define SET_TX_POWER 2 /**< Set transmission power, value -40..+4 dBm in steps of 4 */
#define SELECT_TIMER 3 /**< Select on of the 16 MHz timers 0, 1 or 2 */
#define LE_PACKET_REPORTING_EVENT 0x8000 /**< DTM Packet reporting event, returned by the device to the tester. */
#define LE_TEST_STATUS_EVENT_SUCCESS 0x0000 /**< DTM Status event, indicating success. */
#define LE_TEST_STATUS_EVENT_ERROR 0x0001 /**< DTM Status event, indicating an error. */
#define DTM_PKT_PRBS9 0x00 /**< Bit pattern PRBS9. */
#define DTM_PKT_0X0F 0x01 /**< Bit pattern 11110000 (LSB is the leftmost bit). */
#define DTM_PKT_0X55 0x02 /**< Bit pattern 10101010 (LSB is the leftmost bit). */
#define DTM_PKT_VENDORSPECIFIC 0xFFFFFFFF /**< Vendor specific. Nordic: Continuous carrier test, or configuration. */
/**@brief Return codes from dtm_cmd(). */
#define DTM_SUCCESS 0x00 /**< Indicate that the DTM function completed with success. */
#define DTM_ERROR_ILLEGAL_CHANNEL 0x01 /**< Physical channel number must be in the range 0..39. */
#define DTM_ERROR_INVALID_STATE 0x02 /**< Sequencing error: Command is not valid now. */
#define DTM_ERROR_ILLEGAL_LENGTH 0x03 /**< Payload size must be in the range 0..37. */
#define DTM_ERROR_ILLEGAL_CONFIGURATION 0x04 /**< Parameter out of range (legal range is function dependent). */
#define DTM_ERROR_UNINITIALIZED 0x05 /**< DTM module has not been initialized by the application. */
// Note: DTM_PKT_VENDORSPECIFIC, is not a packet type
#define PACKET_TYPE_MAX DTM_PKT_0X55 /**< Highest value allowed as DTM Packet type. */
/** @brief BLE DTM event type. */
typedef uint32_t dtm_event_t; /**< Type for handling DTM event. */
/** @brief BLE DTM frequency type. */
typedef uint32_t dtm_freq_t; /**< Physical channel, valid range: 0..39. */
/**@brief BLE DTM packet types. */
typedef uint32_t dtm_pkt_type_t; /**< Type for holding the requested DTM payload type.*/
/**@brief Function for initializing or re-initializing DTM module
*
* @return DTM_SUCCESS on successful initialization of the DTM module.
*/
uint32_t dtm_init(void);
/**@brief Function for giving control to dtmlib for handling timer and radio events.
* Will return to caller at 625us intervals or whenever another event than radio occurs
* (such as UART input). Function will put MCU to sleep between events.
*
* @return Time counter, incremented every 625 us.
*/
uint32_t dtm_wait(void);
/**@brief Function for calling when a complete command has been prepared by the Tester.
*
* @param[in] cmd One of the DTM_CMD values (bits 14:15 in the 16-bit UART format).
* @param[in] freq Phys. channel no - actual frequency = (2402 + freq * 2) MHz (bits 8:13 in
* the 16-bit UART format).
* @param[in] length Payload length, 0..37 (bits 2:7 in the 16-bit UART format).
* @param[in] payload One of the DTM_PKT values (bits 0:1 in the 16-bit UART format).
*
* @return DTM_SUCCESS or one of the DTM_ERROR_ values
*/
uint32_t dtm_cmd(dtm_cmd_t cmd, dtm_freq_t freq, uint32_t length, dtm_pkt_type_t payload);
/**@brief Function for reading the result of a DTM command
*
* @param[out] p_dtm_event Pointer to buffer for 16 bit event code according to DTM standard.
*
* @return true: new event, false: no event since last call, this event has been read earlier
*/
bool dtm_event_get(dtm_event_t * p_dtm_event);
/**@brief Function for configuring the timer to use.
*
* @note Must be called when no DTM test is running.
*
* @param[in] new_timer Index (0..2) of timer to be used by the DTM library
*
* @return true: success, new timer was selected, false: parameter error
*/
bool dtm_set_timer(uint32_t new_timer);
/**@brief Function for configuring the transmit power.
*
* @note Must be called when no DTM test is running.
*
* @param[in] new_tx_power New output level, +4..-40, in steps of 4.
*
* @return true: tx power setting changed, false: parameter error
*/
bool dtm_set_txpower(uint32_t new_tx_power);
#endif // BLE_DTM_H__
/** @} */

View File

@ -1,96 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** @file
*
* @defgroup ble_error_log_module Error Log Module
* @{
* @ingroup ble_sdk_lib
* @brief Module for writing error and stack to flash memory.
*
* @details It contains functions for writing an error code, line number, filename/message and
* the stack to the flash during an error, e.g. in the assert handler.
*
*/
#ifndef BLE_ERROR_LOG_H__
#define BLE_ERROR_LOG_H__
#include <stdint.h>
#include <stdbool.h>
#include "ble_flash.h"
#define ERROR_MESSAGE_LENGTH 128 /**< Length of error message to stored. */
#define STACK_DUMP_LENGTH 256 /**< Length of stack to be stored at max: 64 entries of 4 bytes each. */
#define FLASH_PAGE_ERROR_LOG (BLE_FLASH_PAGE_END - 2) /**< Address in flash where stack trace can be stored. */
/**@brief Error Log Data structure.
*
* @details The structure contains the error, message/filename, line number as well as the current
* stack, at the time where an error occured.
*/
typedef struct
{
uint16_t failure; /**< Indication that a major failure has occurred during last execution of the application. */
uint16_t line_number; /**< Line number indicating at which line the failure occurred. */
uint32_t err_code; /**< Error code when failure occurred. */
uint8_t message[ERROR_MESSAGE_LENGTH]; /**< Will just use the first 128 bytes of filename to store for debugging purposes. */
uint32_t stack_info[STACK_DUMP_LENGTH / 4]; /**< Will contain stack information, can be manually unwinded for debug purposes. */
} ble_error_log_data_t;
/**@brief Function for writing the file name/message, line number, and current program stack
* to flash.
*
* @note This function will force the writing to flash, and disregard any radio communication.
* USE THIS FUNCTION WITH CARE.
*
* @param[in] err_code Error code to be logged.
* @param[in] p_message Message to be written to the flash together with stack dump, usually
* the file name where the error occured.
* @param[in] line_number Line number where the error occured.
*
* @return NRF_SUCCESS on successful writing of the error log.
*
*/
uint32_t ble_error_log_write(uint32_t err_code, const uint8_t * p_message, uint16_t line_number);
#endif /* BLE_ERROR_LOG_H__ */
/** @} */

View File

@ -1,84 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ble_racp.h"
#include <stdlib.h>
void ble_racp_decode(uint8_t data_len, uint8_t * p_data, ble_racp_value_t * p_racp_val)
{
p_racp_val->opcode = 0xFF;
p_racp_val->operator = 0xFF;
p_racp_val->operand_len = 0;
p_racp_val->p_operand = NULL;
if (data_len > 0)
{
p_racp_val->opcode = p_data[0];
}
if (data_len > 1)
{
p_racp_val->operator = p_data[1]; //lint !e415
}
if (data_len > 2)
{
p_racp_val->operand_len = data_len - 2;
p_racp_val->p_operand = &p_data[2]; //lint !e416
}
}
uint8_t ble_racp_encode(const ble_racp_value_t * p_racp_val, uint8_t * p_data)
{
uint8_t len = 0;
int i;
if (p_data != NULL)
{
p_data[len++] = p_racp_val->opcode;
p_data[len++] = p_racp_val->operator;
for (i = 0; i < p_racp_val->operand_len; i++)
{
p_data[len++] = p_racp_val->p_operand[i];
}
}
return len;
}

View File

@ -1,123 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** @file
*
* @defgroup ble_sdk_lib_racp Record Access Control Point
* @{
* @ingroup ble_sdk_lib
* @brief Record Access Control Point library.
*/
#ifndef BLE_RACP_H__
#define BLE_RACP_H__
#include <stdint.h>
#include <stdbool.h>
#include "nrf_ble.h"
#include "nrf_ble_types.h"
#include "nrf_ble.h"
/**@brief Record Access Control Point opcodes. */
#define RACP_OPCODE_RESERVED 0 /**< Record Access Control Point opcode - Reserved for future use. */
#define RACP_OPCODE_REPORT_RECS 1 /**< Record Access Control Point opcode - Report stored records. */
#define RACP_OPCODE_DELETE_RECS 2 /**< Record Access Control Point opcode - Delete stored records. */
#define RACP_OPCODE_ABORT_OPERATION 3 /**< Record Access Control Point opcode - Abort operation. */
#define RACP_OPCODE_REPORT_NUM_RECS 4 /**< Record Access Control Point opcode - Report number of stored records. */
#define RACP_OPCODE_NUM_RECS_RESPONSE 5 /**< Record Access Control Point opcode - Number of stored records response. */
#define RACP_OPCODE_RESPONSE_CODE 6 /**< Record Access Control Point opcode - Response code. */
/**@brief Record Access Control Point operators. */
#define RACP_OPERATOR_NULL 0 /**< Record Access Control Point operator - Null. */
#define RACP_OPERATOR_ALL 1 /**< Record Access Control Point operator - All records. */
#define RACP_OPERATOR_LESS_OR_EQUAL 2 /**< Record Access Control Point operator - Less than or equal to. */
#define RACP_OPERATOR_GREATER_OR_EQUAL 3 /**< Record Access Control Point operator - Greater than or equal to. */
#define RACP_OPERATOR_RANGE 4 /**< Record Access Control Point operator - Within range of (inclusive). */
#define RACP_OPERATOR_FIRST 5 /**< Record Access Control Point operator - First record (i.e. oldest record). */
#define RACP_OPERATOR_LAST 6 /**< Record Access Control Point operator - Last record (i.e. most recent record). */
#define RACP_OPERATOR_RFU_START 7 /**< Record Access Control Point operator - Start of Reserved for Future Use area. */
/**@brief Record Access Control Point response codes. */
#define RACP_RESPONSE_RESERVED 0 /**< Record Access Control Point response code - Reserved for future use. */
#define RACP_RESPONSE_SUCCESS 1 /**< Record Access Control Point response code - Successful operation. */
#define RACP_RESPONSE_OPCODE_UNSUPPORTED 2 /**< Record Access Control Point response code - Unsupported op code received. */
#define RACP_RESPONSE_INVALID_OPERATOR 3 /**< Record Access Control Point response code - Operator not valid for service. */
#define RACP_RESPONSE_OPERATOR_UNSUPPORTED 4 /**< Record Access Control Point response code - Unsupported operator. */
#define RACP_RESPONSE_INVALID_OPERAND 5 /**< Record Access Control Point response code - Operand not valid for service. */
#define RACP_RESPONSE_NO_RECORDS_FOUND 6 /**< Record Access Control Point response code - No matching records found. */
#define RACP_RESPONSE_ABORT_FAILED 7 /**< Record Access Control Point response code - Abort could not be completed. */
#define RACP_RESPONSE_PROCEDURE_NOT_DONE 8 /**< Record Access Control Point response code - Procedure could not be completed. */
#define RACP_RESPONSE_OPERAND_UNSUPPORTED 9 /**< Record Access Control Point response code - Unsupported operand. */
/**@brief Record Access Control Point value structure. */
typedef struct
{
uint8_t opcode; /**< Op Code. */
uint8_t operator; /**< Operator. */
uint8_t operand_len; /**< Length of the operand. */
uint8_t * p_operand; /**< Pointer to the operand. */
} ble_racp_value_t;
/**@brief Function for decoding a Record Access Control Point write.
*
* @details This call decodes a write to the Record Access Control Point.
*
* @param[in] data_len Length of data in received write.
* @param[in] p_data Pointer to received data.
* @param[out] p_racp_val Pointer to decoded Record Access Control Point write.
* @note This does not do a data copy. It assumes the data pointed to by
* p_data is persistant until no longer needed.
*/
void ble_racp_decode(uint8_t data_len, uint8_t * p_data, ble_racp_value_t * p_racp_val);
/**@brief Function for encoding a Record Access Control Point response.
*
* @details This call encodes a response from the Record Access Control Point response.
*
* @param[in] p_racp_val Pointer to Record Access Control Point to encode.
* @param[out] p_data Pointer to where encoded data is written.
* NOTE! It is calling routines respsonsibility to make sure.
*
* @return Length of encoded data.
*/
uint8_t ble_racp_encode(const ble_racp_value_t * p_racp_val, uint8_t * p_data);
#endif // BLE_RACP_H__
/** @} */

View File

@ -1,88 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ble_radio_notification.h"
#include <stdlib.h>
#include "nrf_nvic.h"
static bool m_radio_active = false; /**< Current radio state. */
static ble_radio_notification_evt_handler_t m_evt_handler = NULL; /**< Application event handler for handling Radio Notification events. */
void SWI1_IRQHandler(void)
{
m_radio_active = !m_radio_active;
if (m_evt_handler != NULL)
{
m_evt_handler(m_radio_active);
}
}
uint32_t ble_radio_notification_init(uint32_t irq_priority,
uint8_t distance,
ble_radio_notification_evt_handler_t evt_handler)
{
uint32_t err_code;
m_evt_handler = evt_handler;
// Initialize Radio Notification software interrupt
err_code = sd_nvic_ClearPendingIRQ(SWI1_IRQn);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
err_code = sd_nvic_SetPriority(SWI1_IRQn, irq_priority);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
err_code = sd_nvic_EnableIRQ(SWI1_IRQn);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
// Configure the event
return sd_radio_notification_cfg_set(NRF_RADIO_NOTIFICATION_TYPE_INT_ON_BOTH, distance);
}

View File

@ -1,74 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** @file
*
* @defgroup ble_radio_notification Radio Notification Event Handler
* @{
* @ingroup ble_sdk_lib
* @brief Module for propagating Radio Notification events to the application.
*/
#ifndef BLE_RADIO_NOTIFICATION_H__
#define BLE_RADIO_NOTIFICATION_H__
#include <stdint.h>
#include <stdbool.h>
#include "nrf_soc.h"
/**@brief Application radio notification event handler type. */
typedef void (*ble_radio_notification_evt_handler_t) (bool radio_active);
/**@brief Function for initializing the Radio Notification module.
*
* @param[in] irq_priority Interrupt priority for the Radio Notification interrupt handler.
* @param[in] distance The time from an Active event until the radio is activated.
* @param[in] evt_handler Handler to be executed when a radio notification event has been
* received.
*
* @return NRF_SUCCESS on successful initialization, otherwise an error code.
*/
uint32_t ble_radio_notification_init(uint32_t irq_priority,
uint8_t distance,
ble_radio_notification_evt_handler_t evt_handler);
#endif // BLE_RADIO_NOTIFICATION_H__
/** @} */

View File

@ -1,676 +0,0 @@
/*
* Copyright (c) 2013 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ble_dfu.h"
#include "nrf_ble_types.h"
#include "nrf_ble_gatts.h"
#include "ble_srv_common.h"
#include <stddef.h>
#include "sdk_common.h"
#define MAX_DFU_PKT_LEN 20 /**< Maximum length (in bytes) of the DFU Packet characteristic. */
#define PKT_START_DFU_PARAM_LEN 2 /**< Length (in bytes) of the parameters for Packet Start DFU Request. */
#define PKT_INIT_DFU_PARAM_LEN 2 /**< Length (in bytes) of the parameters for Packet Init DFU Request. */
#define PKT_RCPT_NOTIF_REQ_LEN 3 /**< Length (in bytes) of the Packet Receipt Notification Request. */
#define MAX_PKTS_RCPT_NOTIF_LEN 6 /**< Maximum length (in bytes) of the Packets Receipt Notification. */
#define MAX_RESPONSE_LEN 7 /**< Maximum length (in bytes) of the response to a Control Point command. */
#define MAX_NOTIF_BUFFER_LEN MAX(MAX_PKTS_RCPT_NOTIF_LEN, MAX_RESPONSE_LEN) /**< Maximum length (in bytes) of the buffer needed by DFU Service while sending notifications to peer. */
enum
{
OP_CODE_START_DFU = 1, /**< Value of the Op code field for 'Start DFU' command.*/
OP_CODE_RECEIVE_INIT = 2, /**< Value of the Op code field for 'Initialize DFU parameters' command.*/
OP_CODE_RECEIVE_FW = 3, /**< Value of the Op code field for 'Receive firmware image' command.*/
OP_CODE_VALIDATE = 4, /**< Value of the Op code field for 'Validate firmware' command.*/
OP_CODE_ACTIVATE_N_RESET = 5, /**< Value of the Op code field for 'Activate & Reset' command.*/
OP_CODE_SYS_RESET = 6, /**< Value of the Op code field for 'Reset System' command.*/
OP_CODE_IMAGE_SIZE_REQ = 7, /**< Value of the Op code field for 'Report received image size' command.*/
OP_CODE_PKT_RCPT_NOTIF_REQ = 8, /**< Value of the Op code field for 'Request packet receipt notification.*/
OP_CODE_RESPONSE = 16, /**< Value of the Op code field for 'Response.*/
OP_CODE_PKT_RCPT_NOTIF = 17 /**< Value of the Op code field for 'Packets Receipt Notification'.*/
};
static bool m_is_dfu_service_initialized = false; /**< Variable to check if the DFU service was initialized by the application.*/
static uint8_t m_notif_buffer[MAX_NOTIF_BUFFER_LEN]; /**< Buffer used for sending notifications to peer. */
/**@brief Function for adding DFU Packet characteristic to the BLE Stack.
*
* @param[in] p_dfu DFU Service structure.
*
* @return NRF_SUCCESS on success. Otherwise an error code.
*/
static uint32_t dfu_pkt_char_add(ble_dfu_t * const p_dfu)
{
ble_gatts_char_md_t char_md;
ble_gatts_attr_t attr_char_value;
ble_uuid_t char_uuid;
ble_gatts_attr_md_t attr_md;
memset(&char_md, 0, sizeof(char_md));
char_md.char_props.write_wo_resp = 1;
char_md.p_char_user_desc = NULL;
char_md.p_char_pf = NULL;
char_md.p_user_desc_md = NULL;
char_md.p_cccd_md = NULL;
char_md.p_sccd_md = NULL;
char_uuid.type = p_dfu->uuid_type;
char_uuid.uuid = BLE_DFU_PKT_CHAR_UUID;
memset(&attr_md, 0, sizeof(attr_md));
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
attr_md.vloc = BLE_GATTS_VLOC_STACK;
attr_md.rd_auth = 0;
attr_md.wr_auth = 0;
attr_md.vlen = 1;
memset(&attr_char_value, 0, sizeof(attr_char_value));
attr_char_value.p_uuid = &char_uuid;
attr_char_value.p_attr_md = &attr_md;
attr_char_value.init_len = 0;
attr_char_value.init_offs = 0;
attr_char_value.max_len = MAX_DFU_PKT_LEN;
attr_char_value.p_value = NULL;
return sd_ble_gatts_characteristic_add(p_dfu->service_handle,
&char_md,
&attr_char_value,
&p_dfu->dfu_pkt_handles);
}
/**@brief Function for adding DFU Revision characteristic to the BLE Stack.
*
* @param[in] p_dfu DFU Service structure.
*
* @return NRF_SUCCESS on success. Otherwise an error code.
*/
static uint32_t dfu_rev_char_add(ble_dfu_t * const p_dfu, ble_dfu_init_t const * const p_dfu_init)
{
ble_gatts_char_md_t char_md;
ble_gatts_attr_t attr_char_value;
ble_uuid_t char_uuid;
ble_gatts_attr_md_t attr_md;
memset(&char_md, 0, sizeof(char_md));
char_md.char_props.read = 1;
char_md.p_char_user_desc = NULL;
char_md.p_char_pf = NULL;
char_md.p_user_desc_md = NULL;
char_md.p_cccd_md = NULL;
char_md.p_sccd_md = NULL;
char_uuid.type = p_dfu->uuid_type;
char_uuid.uuid = BLE_DFU_REV_CHAR_UUID;
memset(&attr_md, 0, sizeof(attr_md));
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.write_perm);
attr_md.vloc = BLE_GATTS_VLOC_STACK;
attr_md.rd_auth = 0;
attr_md.wr_auth = 0;
attr_md.vlen = 1;
memset(&attr_char_value, 0, sizeof(attr_char_value));
attr_char_value.p_uuid = &char_uuid;
attr_char_value.p_attr_md = &attr_md;
attr_char_value.init_len = sizeof(uint16_t);
attr_char_value.init_offs = 0;
attr_char_value.max_len = sizeof(uint16_t);
attr_char_value.p_value = (uint8_t *)&p_dfu_init->revision;
return sd_ble_gatts_characteristic_add(p_dfu->service_handle,
&char_md,
&attr_char_value,
&p_dfu->dfu_rev_handles);
}
/**@brief Function for adding DFU Control Point characteristic to the BLE Stack.
*
* @param[in] p_dfu DFU Service structure.
*
* @return NRF_SUCCESS on success. Otherwise an error code.
*/
static uint32_t dfu_ctrl_pt_add(ble_dfu_t * const p_dfu)
{
ble_gatts_char_md_t char_md;
ble_gatts_attr_t attr_char_value;
ble_uuid_t char_uuid;
ble_gatts_attr_md_t attr_md;
memset(&char_md, 0, sizeof(char_md));
char_md.char_props.write = 1;
char_md.char_props.notify = 1;
char_md.p_char_user_desc = NULL;
char_md.p_char_pf = NULL;
char_md.p_user_desc_md = NULL;
char_md.p_cccd_md = NULL;
char_md.p_sccd_md = NULL;
char_uuid.type = p_dfu->uuid_type;
char_uuid.uuid = BLE_DFU_CTRL_PT_UUID;
memset(&attr_md, 0, sizeof(attr_md));
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(&attr_md.read_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
attr_md.vloc = BLE_GATTS_VLOC_STACK;
attr_md.rd_auth = 0;
attr_md.wr_auth = 1;
attr_md.vlen = 1;
memset(&attr_char_value, 0, sizeof(attr_char_value));
attr_char_value.p_uuid = &char_uuid;
attr_char_value.p_attr_md = &attr_md;
attr_char_value.init_len = 0;
attr_char_value.init_offs = 0;
attr_char_value.max_len = BLE_L2CAP_MTU_DEF;
attr_char_value.p_value = NULL;
return sd_ble_gatts_characteristic_add(p_dfu->service_handle,
&char_md,
&attr_char_value,
&p_dfu->dfu_ctrl_pt_handles);
}
/**@brief Function for handling the @ref BLE_GAP_EVT_CONNECTED event from the S110 SoftDevice.
*
* @param[in] p_dfu DFU Service Structure.
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
*/
static void on_connect(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
{
p_dfu->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
}
/**@brief Function for checking if the CCCD of DFU Control point is configured for Notification.
*
* @details This function checks if the CCCD of DFU Control Point characteristic is configured
* for Notification by the DFU Controller.
*
* @param[in] p_dfu DFU Service structure.
*
* @return True if the CCCD of DFU Control Point characteristic is configured for Notification.
* False otherwise.
*/
static bool is_cccd_configured(ble_dfu_t * p_dfu)
{
// Check if the CCCDs are configured.
uint8_t cccd_val_buf[BLE_CCCD_VALUE_LEN];
ble_gatts_value_t gatts_value;
// Initialize value struct.
memset(&gatts_value, 0, sizeof(gatts_value));
gatts_value.len = BLE_CCCD_VALUE_LEN;
gatts_value.offset = 0;
gatts_value.p_value = cccd_val_buf;
// Check the CCCD Value of DFU Control Point.
uint32_t err_code = sd_ble_gatts_value_get(p_dfu->conn_handle,
p_dfu->dfu_ctrl_pt_handles.cccd_handle,
&gatts_value);
if (err_code != NRF_SUCCESS)
{
if (p_dfu->error_handler != NULL)
{
p_dfu->error_handler(err_code);
}
return false;
}
return ble_srv_is_notification_enabled(cccd_val_buf);
}
/**@brief Function for handling a Write event on the Control Point characteristic.
*
* @param[in] p_dfu DFU Service Structure.
* @param[in] p_ble_write_evt Pointer to the write event received from BLE stack.
*
* @return NRF_SUCCESS on successful processing of control point write. Otherwise an error code.
*/
static uint32_t on_ctrl_pt_write(ble_dfu_t * p_dfu, ble_gatts_evt_write_t * p_ble_write_evt)
{
ble_gatts_rw_authorize_reply_params_t auth_reply;
auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
auth_reply.params.write.update = 1;
auth_reply.params.write.offset = p_ble_write_evt->offset;
auth_reply.params.write.len = p_ble_write_evt->len;
auth_reply.params.write.p_data = p_ble_write_evt->data;
if (!is_cccd_configured(p_dfu))
{
// Send an error response to the peer indicating that the CCCD is improperly configured.
auth_reply.params.write.gatt_status =
BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR;
return (sd_ble_gatts_rw_authorize_reply(p_dfu->conn_handle, &auth_reply));
}
else
{
uint32_t err_code;
auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
err_code = (sd_ble_gatts_rw_authorize_reply(p_dfu->conn_handle, &auth_reply));
VERIFY_SUCCESS(err_code);
}
ble_dfu_evt_t ble_dfu_evt;
switch (p_ble_write_evt->data[0])
{
case OP_CODE_START_DFU:
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_START;
if (p_ble_write_evt->len < PKT_START_DFU_PARAM_LEN)
{
return ble_dfu_response_send(p_dfu,
(ble_dfu_procedure_t) p_ble_write_evt->data[0],
BLE_DFU_RESP_VAL_OPER_FAILED);
}
ble_dfu_evt.evt.ble_dfu_pkt_write.len = 1;
ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = &(p_ble_write_evt->data[1]);
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
break;
case OP_CODE_RECEIVE_INIT:
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_RECEIVE_INIT_DATA;
if (p_ble_write_evt->len < PKT_INIT_DFU_PARAM_LEN)
{
return ble_dfu_response_send(p_dfu,
(ble_dfu_procedure_t) p_ble_write_evt->data[0],
BLE_DFU_RESP_VAL_OPER_FAILED);
}
ble_dfu_evt.evt.ble_dfu_pkt_write.len = 1;
ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = &(p_ble_write_evt->data[1]);
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
break;
case OP_CODE_RECEIVE_FW:
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_RECEIVE_APP_DATA;
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
break;
case OP_CODE_VALIDATE:
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_VALIDATE;
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
break;
case OP_CODE_ACTIVATE_N_RESET:
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_ACTIVATE_N_RESET;
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
break;
case OP_CODE_SYS_RESET:
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_SYS_RESET;
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
break;
case OP_CODE_PKT_RCPT_NOTIF_REQ:
if (p_ble_write_evt->len < PKT_RCPT_NOTIF_REQ_LEN)
{
return (ble_dfu_response_send(p_dfu,
BLE_DFU_PKT_RCPT_REQ_PROCEDURE,
BLE_DFU_RESP_VAL_NOT_SUPPORTED));
}
ble_dfu_evt.evt.pkt_rcpt_notif_req.num_of_pkts =
uint16_decode(&(p_ble_write_evt->data[1]));
if (ble_dfu_evt.evt.pkt_rcpt_notif_req.num_of_pkts == 0)
{
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PKT_RCPT_NOTIF_DISABLED;
}
else
{
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PKT_RCPT_NOTIF_ENABLED;
}
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
break;
case OP_CODE_IMAGE_SIZE_REQ:
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_BYTES_RECEIVED_SEND;
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
break;
default:
// Unsupported op code.
return ble_dfu_response_send(p_dfu,
(ble_dfu_procedure_t) p_ble_write_evt->data[0],
BLE_DFU_RESP_VAL_NOT_SUPPORTED);
}
return NRF_SUCCESS;
}
/**@brief Function for handling the @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event from the S110
* Stack.
*
* @param[in] p_dfu DFU Service Structure.
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
*/
static void on_rw_authorize_req(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
{
ble_gatts_evt_rw_authorize_request_t * p_authorize_request;
p_authorize_request = &(p_ble_evt->evt.gatts_evt.params.authorize_request);
if (
(p_authorize_request->type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
&&
(p_authorize_request->request.write.handle == p_dfu->dfu_ctrl_pt_handles.value_handle)
&&
(p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op != BLE_GATTS_OP_PREP_WRITE_REQ)
&&
(p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_NOW)
&&
(p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.op != BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)
)
{
uint32_t err_code;
err_code = on_ctrl_pt_write(p_dfu, &(p_authorize_request->request.write));
if (err_code != NRF_SUCCESS && p_dfu->error_handler != NULL)
{
p_dfu->error_handler(err_code);
}
}
}
/**@brief Function for handling the @ref BLE_GATTS_EVT_WRITE event from the S110 SoftDevice.
*
* @param[in] p_dfu DFU Service Structure.
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
*/
static void on_write(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
{
if (p_ble_evt->evt.gatts_evt.params.write.handle == p_dfu->dfu_pkt_handles.value_handle)
{
// DFU Packet written
ble_dfu_evt_t ble_dfu_evt;
ble_dfu_evt.ble_dfu_evt_type = BLE_DFU_PACKET_WRITE;
ble_dfu_evt.evt.ble_dfu_pkt_write.len = p_ble_evt->evt.gatts_evt.params.write.len;
ble_dfu_evt.evt.ble_dfu_pkt_write.p_data = p_ble_evt->evt.gatts_evt.params.write.data;
p_dfu->evt_handler(p_dfu, &ble_dfu_evt);
}
}
/**@brief Function for handling the BLE_GAP_EVT_DISCONNECTED event from the S110 SoftDevice.
*
* @param[in] p_dfu DFU Service Structure.
* @param[in] p_ble_evt Pointer to the event received from BLE stack.
*/
static void on_disconnect(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
{
p_dfu->conn_handle = BLE_CONN_HANDLE_INVALID;
}
uint32_t ble_dfu_init(ble_dfu_t * p_dfu, ble_dfu_init_t * p_dfu_init)
{
if ((p_dfu == NULL) || (p_dfu_init == NULL) || (p_dfu_init->evt_handler == NULL))
{
return NRF_ERROR_NULL;
}
p_dfu->conn_handle = BLE_CONN_HANDLE_INVALID;
ble_uuid_t service_uuid;
uint32_t err_code;
const ble_uuid128_t base_uuid128 =
{
{
0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
0xDE, 0xEF, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00
}
};
service_uuid.uuid = BLE_DFU_SERVICE_UUID;
err_code = sd_ble_uuid_vs_add(&base_uuid128, &(service_uuid.type));
VERIFY_SUCCESS(err_code);
err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
&service_uuid,
&(p_dfu->service_handle));
VERIFY_SUCCESS(err_code);
p_dfu->uuid_type = service_uuid.type;
err_code = dfu_pkt_char_add(p_dfu);
VERIFY_SUCCESS(err_code);
err_code = dfu_ctrl_pt_add(p_dfu);
VERIFY_SUCCESS(err_code);
err_code = dfu_rev_char_add(p_dfu, p_dfu_init);
VERIFY_SUCCESS(err_code);
p_dfu->evt_handler = p_dfu_init->evt_handler;
if (p_dfu_init->error_handler != NULL)
{
p_dfu->error_handler = p_dfu_init->error_handler;
}
m_is_dfu_service_initialized = true;
return NRF_SUCCESS;
}
void ble_dfu_on_ble_evt(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt)
{
if ((p_dfu == NULL) || (p_ble_evt == NULL))
{
return;
}
if (p_dfu->evt_handler != NULL)
{
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
on_connect(p_dfu, p_ble_evt);
break;
case BLE_GATTS_EVT_WRITE:
on_write(p_dfu, p_ble_evt);
break;
case BLE_GAP_EVT_DISCONNECTED:
on_disconnect(p_dfu, p_ble_evt);
break;
case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
on_rw_authorize_req(p_dfu, p_ble_evt);
break;
default:
// No implementation needed.
break;
}
}
}
uint32_t ble_dfu_bytes_rcvd_report(ble_dfu_t * p_dfu, uint32_t num_of_firmware_bytes_rcvd)
{
if (p_dfu == NULL)
{
return NRF_ERROR_NULL;
}
if ((p_dfu->conn_handle == BLE_CONN_HANDLE_INVALID) || !m_is_dfu_service_initialized)
{
return NRF_ERROR_INVALID_STATE;
}
ble_gatts_hvx_params_t hvx_params;
uint16_t index = 0;
// Encode the Op Code.
m_notif_buffer[index++] = OP_CODE_RESPONSE;
// Encode the Reqest Op Code.
m_notif_buffer[index++] = OP_CODE_IMAGE_SIZE_REQ;
// Encode the Response Value.
m_notif_buffer[index++] = (uint8_t)BLE_DFU_RESP_VAL_SUCCESS;
index += uint32_encode(num_of_firmware_bytes_rcvd, &m_notif_buffer[index]);
memset(&hvx_params, 0, sizeof(hvx_params));
hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle;
hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
hvx_params.offset = 0;
hvx_params.p_len = &index;
hvx_params.p_data = m_notif_buffer;
return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params);
}
uint32_t ble_dfu_pkts_rcpt_notify(ble_dfu_t * p_dfu, uint32_t num_of_firmware_bytes_rcvd)
{
if (p_dfu == NULL)
{
return NRF_ERROR_NULL;
}
if ((p_dfu->conn_handle == BLE_CONN_HANDLE_INVALID) || !m_is_dfu_service_initialized)
{
return NRF_ERROR_INVALID_STATE;
}
ble_gatts_hvx_params_t hvx_params;
uint16_t index = 0;
m_notif_buffer[index++] = OP_CODE_PKT_RCPT_NOTIF;
index += uint32_encode(num_of_firmware_bytes_rcvd, &m_notif_buffer[index]);
memset(&hvx_params, 0, sizeof(hvx_params));
hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle;
hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
hvx_params.offset = 0;
hvx_params.p_len = &index;
hvx_params.p_data = m_notif_buffer;
return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params);
}
uint32_t ble_dfu_response_send(ble_dfu_t * p_dfu,
ble_dfu_procedure_t dfu_proc,
ble_dfu_resp_val_t resp_val)
{
if (p_dfu == NULL)
{
return NRF_ERROR_NULL;
}
if ((p_dfu->conn_handle == BLE_CONN_HANDLE_INVALID) || !m_is_dfu_service_initialized)
{
return NRF_ERROR_INVALID_STATE;
}
ble_gatts_hvx_params_t hvx_params;
uint16_t index = 0;
m_notif_buffer[index++] = OP_CODE_RESPONSE;
// Encode the Request Op code
m_notif_buffer[index++] = (uint8_t)dfu_proc;
// Encode the Response Value.
m_notif_buffer[index++] = (uint8_t)resp_val;
memset(&hvx_params, 0, sizeof(hvx_params));
hvx_params.handle = p_dfu->dfu_ctrl_pt_handles.value_handle;
hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
hvx_params.offset = 0;
hvx_params.p_len = &index;
hvx_params.p_data = m_notif_buffer;
return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params);
}

View File

@ -1,266 +0,0 @@
/*
* Copyright (c) 2013 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**@file
*
* @defgroup ble_sdk_srv_dfu Device Firmware Update Service
* @{
* @ingroup ble_sdk_srv
* @brief Device Firmware Update Service
*
* @details The Device Firmware Update (DFU) service is a GATT based service that can be used for
* performing firmware updates over BLE. Note that this implementation uses vendor
* specific UUIDs for service and characteristics and is intended to demonstrate the
* firmware updates over BLE. Refer @ref bledfu_transport_bleservice and @ref
* bledfu_transport_bleprofile for more information on the service and profile respectively.
*/
#ifndef BLE_DFU_H__
#define BLE_DFU_H__
#include <stdint.h>
#include "nrf_ble_gatts.h"
#include "nrf_ble_gap.h"
#include "nrf_ble.h"
#include "ble_srv_common.h"
#define BLE_DFU_SERVICE_UUID 0x1530 /**< The UUID of the DFU Service. */
#define BLE_DFU_PKT_CHAR_UUID 0x1532 /**< The UUID of the DFU Packet Characteristic. */
#define BLE_DFU_CTRL_PT_UUID 0x1531 /**< The UUID of the DFU Control Point. */
#define BLE_DFU_STATUS_REP_UUID 0x1533 /**< The UUID of the DFU Status Report Characteristic. */
#define BLE_DFU_REV_CHAR_UUID 0x1534 /**< The UUID of the DFU Revision Characteristic. */
/**@brief DFU Event type.
*
* @details This enumeration contains the types of events that will be received from the DFU Service.
*/
typedef enum
{
BLE_DFU_START, /**< The event indicating that the peer wants the application to prepare for a new firmware update. */
BLE_DFU_RECEIVE_INIT_DATA, /**< The event indicating that the peer wants the application to prepare to receive init parameters. */
BLE_DFU_RECEIVE_APP_DATA, /**< The event indicating that the peer wants the application to prepare to receive the new firmware image. */
BLE_DFU_VALIDATE, /**< The event indicating that the peer wants the application to validate the newly received firmware image. */
BLE_DFU_ACTIVATE_N_RESET, /**< The event indicating that the peer wants the application to undergo activate new firmware and restart with new valid application */
BLE_DFU_SYS_RESET, /**< The event indicating that the peer wants the application to undergo a reset and start the currently valid application image.*/
BLE_DFU_PKT_RCPT_NOTIF_ENABLED, /**< The event indicating that the peer has enabled packet receipt notifications. It is the responsibility of the application to call @ref ble_dfu_pkts_rcpt_notify each time the number of packets indicated by num_of_pkts field in @ref ble_dfu_evt_t is received.*/
BLE_DFU_PKT_RCPT_NOTIF_DISABLED, /**< The event indicating that the peer has disabled the packet receipt notifications.*/
BLE_DFU_PACKET_WRITE, /**< The event indicating that the peer has written a value to the 'DFU Packet' characteristic. The data received from the peer will be present in the @ref BLE_DFU_PACKET_WRITE element contained within @ref ble_dfu_evt_t.*/
BLE_DFU_BYTES_RECEIVED_SEND /**< The event indicating that the peer is requesting for the number of bytes of firmware data last received by the application. It is the responsibility of the application to call @ref ble_dfu_pkts_rcpt_notify in response to this event. */
} ble_dfu_evt_type_t;
/**@brief DFU Procedure type.
*
* @details This enumeration contains the types of DFU procedures.
*/
typedef enum
{
BLE_DFU_START_PROCEDURE = 1, /**< DFU Start procedure.*/
BLE_DFU_INIT_PROCEDURE = 2, /**< DFU Initialization procedure.*/
BLE_DFU_RECEIVE_APP_PROCEDURE = 3, /**< Firmware receiving procedure.*/
BLE_DFU_VALIDATE_PROCEDURE = 4, /**< Firmware image validation procedure .*/
BLE_DFU_PKT_RCPT_REQ_PROCEDURE = 8 /**< Packet receipt notification request procedure. */
} ble_dfu_procedure_t;
/**@brief DFU Response value type.
*/
typedef enum
{
BLE_DFU_RESP_VAL_SUCCESS = 1, /**< Success.*/
BLE_DFU_RESP_VAL_INVALID_STATE, /**< Invalid state.*/
BLE_DFU_RESP_VAL_NOT_SUPPORTED, /**< Operation not supported.*/
BLE_DFU_RESP_VAL_DATA_SIZE, /**< Data size exceeds limit.*/
BLE_DFU_RESP_VAL_CRC_ERROR, /**< CRC Error.*/
BLE_DFU_RESP_VAL_OPER_FAILED /**< Operation failed.*/
} ble_dfu_resp_val_t;
/**@brief DFU Packet structure.
*
* @details This structure contains the value of the DFU Packet characteristic as written by the
* peer and the length of the value written. It will be filled by the DFU Service when the
* peer writes to the DFU Packet characteristic.
*/
typedef struct
{
uint8_t * p_data; /**< Pointer to the received packet. This will point to a word aligned memory location.*/
uint8_t len; /**< Length of the packet received. */
} ble_dfu_pkt_write_t;
/**@brief Packet receipt notification request structure.
*
* @details This structure contains the contents of the packet receipt notification request
* sent by the DFU Controller.
*/
typedef struct
{
uint16_t num_of_pkts; /**< The number of packets of firmware data to be received by application before sending the next Packet Receipt Notification to the peer. */
} ble_pkt_rcpt_notif_req_t;
/**@brief DFU Event structure.
*
* @details This structure contains the event generated by the DFU Service based on the data
* received from the peer.
*/
typedef struct
{
ble_dfu_evt_type_t ble_dfu_evt_type; /**< Type of the event.*/
union
{
ble_dfu_pkt_write_t ble_dfu_pkt_write; /**< The DFU packet received. This field is when the @ref ble_dfu_evt_type field is set to @ref BLE_DFU_PACKET_WRITE.*/
ble_pkt_rcpt_notif_req_t pkt_rcpt_notif_req; /**< Packet receipt notification request. This field is when the @ref ble_dfu_evt_type field is set to @ref BLE_DFU_PKT_RCPT_NOTIF_ENABLED.*/
} evt;
} ble_dfu_evt_t;
// Forward declaration of the ble_dfu_t type.
typedef struct ble_dfu_s ble_dfu_t;
/**@brief DFU Service event handler type. */
typedef void (*ble_dfu_evt_handler_t) (ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt);
/**@brief DFU service structure.
*
* @details This structure contains status information related to the service.
*/
struct ble_dfu_s
{
uint16_t conn_handle; /**< Handle of the current connection (as provided by the SoftDevice). This will be BLE_CONN_HANDLE_INVALID when not in a connection. */
uint16_t revision; /**< Handle of DFU Service (as provided by the SoftDevice). */
uint16_t service_handle; /**< Handle of DFU Service (as provided by the SoftDevice). */
uint8_t uuid_type; /**< UUID type assigned for DFU Service by the SoftDevice. */
ble_gatts_char_handles_t dfu_pkt_handles; /**< Handles related to the DFU Packet characteristic. */
ble_gatts_char_handles_t dfu_ctrl_pt_handles; /**< Handles related to the DFU Control Point characteristic. */
ble_gatts_char_handles_t dfu_status_rep_handles; /**< Handles related to the DFU Status Report characteristic. */
ble_gatts_char_handles_t dfu_rev_handles; /**< Handles related to the DFU Revision characteristic. */
ble_dfu_evt_handler_t evt_handler; /**< The event handler to be called when an event is to be sent to the application.*/
ble_srv_error_handler_t error_handler; /**< Function to be called in case of an error. */
};
/**@brief DFU service initialization structure.
*
* @details This structure contains the initialization information for the DFU Service. The
* application needs to fill this structure and pass it to the DFU Service using the
* @ref ble_dfu_init function.
*/
typedef struct
{
uint16_t revision; /**< Revision number to be exposed by the DFU service. */
ble_dfu_evt_handler_t evt_handler; /**< Event handler to be called for handling events in the Device Firmware Update Service. */
ble_srv_error_handler_t error_handler; /**< Function to be called in case of an error. */
} ble_dfu_init_t;
/**@brief Function for handling a BLE event.
*
* @details The DFU service expects the application to call this function each time an event
* is received from the SoftDevice. This function processes the event, if it is
* relevant for the DFU service and calls the DFU event handler of the application if
* necessary.
*
* @param[in] p_dfu Pointer to the DFU service structure.
* @param[in] p_ble_evt Pointer to the event received from SoftDevice.
*/
void ble_dfu_on_ble_evt(ble_dfu_t * p_dfu, ble_evt_t * p_ble_evt);
/**@brief Function for initializing the DFU service.
*
* @param[out] p_dfu Device Firmware Update service structure. This structure will have to be
* supplied by the application. It will be initialized by this function,
* and will later be used to identify the service instance.
* @param[in] p_dfu_init Information needed to initialize the service.
*
* @return NRF_SUCCESS if the DFU service and its characteristics were successfully added to the
* SoftDevice. Otherwise an error code.
* This function returns NRF_ERROR_NULL if the value of evt_handler in p_dfu_init
* structure provided is NULL or if the pointers supplied as input are NULL.
*/
uint32_t ble_dfu_init(ble_dfu_t * p_dfu, ble_dfu_init_t * p_dfu_init);
/**@brief Function for sending response to a control point command.
*
* @details This function will encode a DFU Control Point response using the given input
* parameters and will send a notification of the same to the peer.
*
* @param[in] p_dfu Pointer to the DFU service structure.
* @param[in] dfu_proc Procedure for which this response is to be sent.
* @param[in] resp_val Response value.
*
* @return NRF_SUCCESS if the DFU Service has successfully requested the SoftDevice to
* send the notification. Otherwise an error code.
* This function returns NRF_ERROR_INVALID_STATE if the device is not connected to a
* peer or if the DFU service is not initialized or if the notification of the DFU
* Status Report characteristic was not enabled by the peer. It returns NRF_ERROR_NULL
* if the pointer p_dfu is NULL.
*/
uint32_t ble_dfu_response_send(ble_dfu_t * p_dfu,
ble_dfu_procedure_t dfu_proc,
ble_dfu_resp_val_t resp_val);
/**@brief Function for notifying the peer about the number of bytes of firmware data received.
*
* @param[in] p_dfu Pointer to the DFU service structure.
* @param[in] num_of_firmware_bytes_rcvd Number of bytes.
*
* @return NRF_SUCCESS if the DFU Service has successfully requested the SoftDevice to send
* the notification. Otherwise an error code.
* This function returns NRF_ERROR_INVALID_STATE if the device is not connected to a
* peer or if the DFU service is not initialized or if the notification of the DFU
* Status Report characteristic was not enabled by the peer. It returns NRF_ERROR_NULL
* if the pointer p_dfu is NULL.
*/
uint32_t ble_dfu_bytes_rcvd_report(ble_dfu_t * p_dfu, uint32_t num_of_firmware_bytes_rcvd);
/**@brief Function for sending Packet Receipt Notification to the peer.
*
* This function will encode the number of bytes received as input parameter into a
* notification of the control point characteristic and send it to the peer.
*
* @param[in] p_dfu Pointer to the DFU service structure.
* @param[in] num_of_firmware_bytes_rcvd Number of bytes of firmware image received.
*
* @return NRF_SUCCESS if the DFU Service has successfully requested the SoftDevice to send
* the notification. Otherwise an error code.
* This function returns NRF_ERROR_INVALID_STATE if the device is not connected to a
* peer or if the DFU service is not initialized or if the notification of the DFU
* Status Report characteristic was not enabled by the peer. It returns NRF_ERROR_NULL
* if the pointer p_dfu is NULL.
*/
uint32_t ble_dfu_pkts_rcpt_notify(ble_dfu_t * p_dfu, uint32_t num_of_firmware_bytes_rcvd);
#endif // BLE_DFU_H__
/** @} */

View File

@ -1,788 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ble_advdata.h"
#include "nrf_ble_gap.h"
#include "ble_srv_common.h"
#include "sdk_common.h"
// NOTE: For now, Security Manager Out of Band Flags (OOB) are omitted from the advertising data.
// Types of LE Bluetooth Device Address AD type
#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_PUBLIC 0UL
#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_RANDOM 1UL
static uint32_t tk_value_encode(ble_advdata_tk_value_t * p_tk_value,
uint8_t * p_encoded_data,
uint16_t * p_offset,
uint16_t max_size)
{
int8_t i;
// Check for buffer overflow.
if (((*p_offset) + AD_TYPE_TK_VALUE_SIZE) > max_size)
{
return NRF_ERROR_DATA_SIZE;
}
// Encode LE Role.
p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + AD_TYPE_TK_VALUE_DATA_SIZE);
*p_offset += ADV_LENGTH_FIELD_SIZE;
p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SECURITY_MANAGER_TK_VALUE;
*p_offset += ADV_AD_TYPE_FIELD_SIZE;
for (i = AD_TYPE_TK_VALUE_DATA_SIZE - 1; i >= 0; i--, (*p_offset)++)
{
p_encoded_data[*p_offset] = p_tk_value->tk[i];
}
return NRF_SUCCESS;
}
static uint32_t le_role_encode(ble_advdata_le_role_t le_role,
uint8_t * p_encoded_data,
uint16_t * p_offset,
uint16_t max_size)
{
// Check for buffer overflow.
if (((*p_offset) + AD_TYPE_LE_ROLE_SIZE) > max_size)
{
return NRF_ERROR_DATA_SIZE;
}
// Encode LE Role.
p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + AD_TYPE_LE_ROLE_DATA_SIZE);
*p_offset += ADV_LENGTH_FIELD_SIZE;
p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_LE_ROLE;
*p_offset += ADV_AD_TYPE_FIELD_SIZE;
switch(le_role)
{
case BLE_ADVDATA_ROLE_ONLY_PERIPH:
p_encoded_data[*p_offset] = 0;
break;
case BLE_ADVDATA_ROLE_ONLY_CENTRAL:
p_encoded_data[*p_offset] = 1;
break;
case BLE_ADVDATA_ROLE_BOTH_PERIPH_PREFERRED:
p_encoded_data[*p_offset] = 2;
break;
case BLE_ADVDATA_ROLE_BOTH_CENTRAL_PREFERRED:
p_encoded_data[*p_offset] = 3;
break;
default:
return NRF_ERROR_INVALID_PARAM;
}
*p_offset += AD_TYPE_LE_ROLE_DATA_SIZE;
return NRF_SUCCESS;
}
static uint32_t ble_device_addr_encode(uint8_t * p_encoded_data,
uint16_t * p_offset,
uint16_t max_size)
{
uint32_t err_code;
ble_gap_addr_t device_addr;
// Check for buffer overflow.
if (((*p_offset) + AD_TYPE_BLE_DEVICE_ADDR_SIZE) > max_size)
{
return NRF_ERROR_DATA_SIZE;
}
// Get BLE address
err_code = sd_ble_gap_address_get(&device_addr);
VERIFY_SUCCESS(err_code);
// Encode LE Bluetooth Device Address
p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE +
AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE);
*p_offset += ADV_LENGTH_FIELD_SIZE;
p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS;
*p_offset += ADV_AD_TYPE_FIELD_SIZE;
memcpy(&p_encoded_data[*p_offset], &device_addr.addr[0], BLE_GAP_ADDR_LEN);
*p_offset += BLE_GAP_ADDR_LEN;
if(BLE_GAP_ADDR_TYPE_PUBLIC == device_addr.addr_type)
{
p_encoded_data[*p_offset] = AD_TYPE_BLE_DEVICE_ADDR_TYPE_PUBLIC;
}
else
{
p_encoded_data[*p_offset] = AD_TYPE_BLE_DEVICE_ADDR_TYPE_RANDOM;
}
*p_offset += AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE;
return NRF_SUCCESS;
}
static uint32_t name_encode(const ble_advdata_t * p_advdata,
uint8_t * p_encoded_data,
uint16_t * p_offset,
uint16_t max_size)
{
uint32_t err_code;
uint16_t rem_adv_data_len;
uint16_t actual_length;
uint8_t adv_data_format;
// Validate parameters
if((BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) && (0 == p_advdata->short_name_len))
{
return NRF_ERROR_INVALID_PARAM;
}
// Check for buffer overflow.
if ( (((*p_offset) + ADV_AD_DATA_OFFSET) > max_size) ||
( (BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) &&
(((*p_offset) + ADV_AD_DATA_OFFSET + p_advdata->short_name_len) > max_size)))
{
return NRF_ERROR_DATA_SIZE;
}
rem_adv_data_len = max_size - (*p_offset) - ADV_AD_DATA_OFFSET;
actual_length = rem_adv_data_len;
// Get GAP device name and length
err_code = sd_ble_gap_device_name_get(&p_encoded_data[(*p_offset) + ADV_AD_DATA_OFFSET],
&actual_length);
VERIFY_SUCCESS(err_code);
// Check if device intend to use short name and it can fit available data size.
if ((p_advdata->name_type == BLE_ADVDATA_FULL_NAME) && (actual_length <= rem_adv_data_len))
{
// Complete device name can fit, setting Complete Name in Adv Data.
adv_data_format = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME;
}
else
{
// Else short name needs to be used. Or application has requested use of short name.
adv_data_format = BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME;
// If application has set a preference on the short name size, it needs to be considered,
// else fit what can be fit.
if ((BLE_ADVDATA_SHORT_NAME == p_advdata->name_type) &&
(p_advdata->short_name_len <= rem_adv_data_len))
{
// Short name fits available size.
actual_length = p_advdata->short_name_len;
}
// Else whatever can fit the data buffer will be packed.
else
{
actual_length = rem_adv_data_len;
}
}
// There is only 1 byte intended to encode length which is (actual_length + ADV_AD_TYPE_FIELD_SIZE)
if(actual_length > (0x00FF - ADV_AD_TYPE_FIELD_SIZE))
{
return NRF_ERROR_DATA_SIZE;
}
// Complete name field in encoded data.
p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + actual_length);
*p_offset += ADV_LENGTH_FIELD_SIZE;
p_encoded_data[*p_offset] = adv_data_format;
*p_offset += ADV_AD_TYPE_FIELD_SIZE;
*p_offset += actual_length;
return NRF_SUCCESS;
}
static uint32_t appearance_encode(uint8_t * p_encoded_data,
uint16_t * p_offset,
uint16_t max_size)
{
uint32_t err_code;
uint16_t appearance;
// Check for buffer overflow.
if (((*p_offset) + AD_TYPE_APPEARANCE_SIZE) > max_size)
{
return NRF_ERROR_DATA_SIZE;
}
// Get GAP appearance field.
err_code = sd_ble_gap_appearance_get(&appearance);
VERIFY_SUCCESS(err_code);
// Encode Length, AD Type and Appearance.
p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + AD_TYPE_APPEARANCE_DATA_SIZE);
*p_offset += ADV_LENGTH_FIELD_SIZE;
p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_APPEARANCE;
*p_offset += ADV_AD_TYPE_FIELD_SIZE;
*p_offset += uint16_encode(appearance, &p_encoded_data[*p_offset]);
return NRF_SUCCESS;
}
static uint32_t flags_encode(int8_t flags,
uint8_t * p_encoded_data,
uint16_t * p_offset,
uint16_t max_size)
{
// Check for buffer overflow.
if (((*p_offset) + AD_TYPE_FLAGS_SIZE) > max_size)
{
return NRF_ERROR_DATA_SIZE;
}
// Encode flags.
p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + AD_TYPE_FLAGS_DATA_SIZE);
*p_offset += ADV_LENGTH_FIELD_SIZE;
p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_FLAGS;
*p_offset += ADV_AD_TYPE_FIELD_SIZE;
p_encoded_data[*p_offset] = flags;
*p_offset += AD_TYPE_FLAGS_DATA_SIZE;
return NRF_SUCCESS;
}
static uint32_t sec_mgr_oob_flags_encode(uint8_t oob_flags,
uint8_t * p_encoded_data,
uint16_t * p_offset,
uint16_t max_size)
{
// Check for buffer overflow.
if (((*p_offset) + AD_TYPE_OOB_FLAGS_SIZE) > max_size)
{
return NRF_ERROR_DATA_SIZE;
}
// Encode flags.
p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + AD_TYPE_OOB_FLAGS_DATA_SIZE);
*p_offset += ADV_LENGTH_FIELD_SIZE;
p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SECURITY_MANAGER_OOB_FLAGS;
*p_offset += ADV_AD_TYPE_FIELD_SIZE;
p_encoded_data[*p_offset] = oob_flags;
*p_offset += AD_TYPE_OOB_FLAGS_DATA_SIZE;
return NRF_SUCCESS;
}
static uint32_t tx_power_level_encode(int8_t tx_power_level,
uint8_t * p_encoded_data,
uint16_t * p_offset,
uint16_t max_size)
{
// Check for buffer overflow.
if (((*p_offset) + AD_TYPE_TX_POWER_LEVEL_SIZE) > max_size)
{
return NRF_ERROR_DATA_SIZE;
}
// Encode TX Power Level.
p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE +
AD_TYPE_TX_POWER_LEVEL_DATA_SIZE);
*p_offset += ADV_LENGTH_FIELD_SIZE;
p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_TX_POWER_LEVEL;
*p_offset += ADV_AD_TYPE_FIELD_SIZE;
p_encoded_data[*p_offset] = tx_power_level;
*p_offset += AD_TYPE_TX_POWER_LEVEL_DATA_SIZE;
return NRF_SUCCESS;
}
static uint32_t uuid_list_sized_encode(const ble_advdata_uuid_list_t * p_uuid_list,
uint8_t adv_type,
uint8_t uuid_size,
uint8_t * p_encoded_data,
uint16_t * p_offset,
uint16_t max_size)
{
int i;
bool is_heading_written = false;
uint16_t start_pos = *p_offset;
uint16_t length;
for (i = 0; i < p_uuid_list->uuid_cnt; i++)
{
uint32_t err_code;
uint8_t encoded_size;
ble_uuid_t uuid = p_uuid_list->p_uuids[i];
// Find encoded uuid size.
err_code = sd_ble_uuid_encode(&uuid, &encoded_size, NULL);
VERIFY_SUCCESS(err_code);
// Check size.
if (encoded_size == uuid_size)
{
uint8_t heading_bytes = (is_heading_written) ? 0 : ADV_AD_DATA_OFFSET;
// Check for buffer overflow
if (((*p_offset) + encoded_size + heading_bytes) > max_size)
{
return NRF_ERROR_DATA_SIZE;
}
if (!is_heading_written)
{
// Write AD structure heading.
*p_offset += ADV_LENGTH_FIELD_SIZE;
p_encoded_data[*p_offset] = adv_type;
*p_offset += ADV_AD_TYPE_FIELD_SIZE;
is_heading_written = true;
}
// Write UUID.
err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &p_encoded_data[*p_offset]);
VERIFY_SUCCESS(err_code);
*p_offset += encoded_size;
}
}
if (is_heading_written)
{
// Write length.
length = (*p_offset) - (start_pos + ADV_LENGTH_FIELD_SIZE);
// There is only 1 byte intended to encode length
if(length > 0x00FF)
{
return NRF_ERROR_DATA_SIZE;
}
p_encoded_data[start_pos] = (uint8_t)length;
}
return NRF_SUCCESS;
}
static uint32_t uuid_list_encode(const ble_advdata_uuid_list_t * p_uuid_list,
uint8_t adv_type_16,
uint8_t adv_type_128,
uint8_t * p_encoded_data,
uint16_t * p_offset,
uint16_t max_size)
{
uint32_t err_code;
// Encode 16 bit UUIDs.
err_code = uuid_list_sized_encode(p_uuid_list,
adv_type_16,
sizeof(uint16_le_t),
p_encoded_data,
p_offset,
max_size);
VERIFY_SUCCESS(err_code);
// Encode 128 bit UUIDs.
err_code = uuid_list_sized_encode(p_uuid_list,
adv_type_128,
sizeof(ble_uuid128_t),
p_encoded_data,
p_offset,
max_size);
VERIFY_SUCCESS(err_code);
return NRF_SUCCESS;
}
static uint32_t conn_int_check(const ble_advdata_conn_int_t *p_conn_int)
{
// Check Minimum Connection Interval.
if ((p_conn_int->min_conn_interval < 0x0006) ||
(
(p_conn_int->min_conn_interval > 0x0c80) &&
(p_conn_int->min_conn_interval != 0xffff)
)
)
{
return NRF_ERROR_INVALID_PARAM;
}
// Check Maximum Connection Interval.
if ((p_conn_int->max_conn_interval < 0x0006) ||
(
(p_conn_int->max_conn_interval > 0x0c80) &&
(p_conn_int->max_conn_interval != 0xffff)
)
)
{
return NRF_ERROR_INVALID_PARAM;
}
// Make sure Minimum Connection Interval is not bigger than Maximum Connection Interval.
if ((p_conn_int->min_conn_interval != 0xffff) &&
(p_conn_int->max_conn_interval != 0xffff) &&
(p_conn_int->min_conn_interval > p_conn_int->max_conn_interval)
)
{
return NRF_ERROR_INVALID_PARAM;
}
return NRF_SUCCESS;
}
static uint32_t conn_int_encode(const ble_advdata_conn_int_t * p_conn_int,
uint8_t * p_encoded_data,
uint16_t * p_offset,
uint16_t max_size)
{
uint32_t err_code;
// Check for buffer overflow.
if (((*p_offset) + AD_TYPE_CONN_INT_SIZE) > max_size)
{
return NRF_ERROR_DATA_SIZE;
}
// Check parameters.
err_code = conn_int_check(p_conn_int);
VERIFY_SUCCESS(err_code);
// Encode Length and AD Type.
p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + AD_TYPE_CONN_INT_DATA_SIZE);
*p_offset += ADV_LENGTH_FIELD_SIZE;
p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE;
*p_offset += ADV_AD_TYPE_FIELD_SIZE;
// Encode Minimum and Maximum Connection Intervals.
*p_offset += uint16_encode(p_conn_int->min_conn_interval, &p_encoded_data[*p_offset]);
*p_offset += uint16_encode(p_conn_int->max_conn_interval, &p_encoded_data[*p_offset]);
return NRF_SUCCESS;
}
static uint32_t manuf_specific_data_encode(const ble_advdata_manuf_data_t * p_manuf_sp_data,
uint8_t * p_encoded_data,
uint16_t * p_offset,
uint16_t max_size)
{
uint32_t data_size = AD_TYPE_MANUF_SPEC_DATA_ID_SIZE + p_manuf_sp_data->data.size;
// Check for buffer overflow.
if (((*p_offset) + ADV_AD_DATA_OFFSET + data_size) > max_size)
{
return NRF_ERROR_DATA_SIZE;
}
// There is only 1 byte intended to encode length which is (data_size + ADV_AD_TYPE_FIELD_SIZE)
if(data_size > (0x00FF - ADV_AD_TYPE_FIELD_SIZE))
{
return NRF_ERROR_DATA_SIZE;
}
// Encode Length and AD Type.
p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + data_size);
*p_offset += ADV_LENGTH_FIELD_SIZE;
p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_MANUFACTURER_SPECIFIC_DATA;
*p_offset += ADV_AD_TYPE_FIELD_SIZE;
// Encode Company Identifier.
*p_offset += uint16_encode(p_manuf_sp_data->company_identifier, &p_encoded_data[*p_offset]);
// Encode additional manufacturer specific data.
if (p_manuf_sp_data->data.size > 0)
{
if (p_manuf_sp_data->data.p_data == NULL)
{
return NRF_ERROR_INVALID_PARAM;
}
memcpy(&p_encoded_data[*p_offset], p_manuf_sp_data->data.p_data, p_manuf_sp_data->data.size);
*p_offset += p_manuf_sp_data->data.size;
}
return NRF_SUCCESS;
}
// Implemented only for 16-bit UUIDs
static uint32_t service_data_encode(const ble_advdata_t * p_advdata,
uint8_t * p_encoded_data,
uint16_t * p_offset,
uint16_t max_size)
{
uint8_t i;
// Check parameter consistency.
if (p_advdata->p_service_data_array == NULL)
{
return NRF_ERROR_INVALID_PARAM;
}
for (i = 0; i < p_advdata->service_data_count; i++)
{
ble_advdata_service_data_t * p_service_data;
uint32_t data_size;
p_service_data = &p_advdata->p_service_data_array[i];
// For now implemented only for 16-bit UUIDs
data_size = AD_TYPE_SERV_DATA_16BIT_UUID_SIZE + p_service_data->data.size;
// There is only 1 byte intended to encode length which is (data_size + ADV_AD_TYPE_FIELD_SIZE)
if(data_size > (0x00FF - ADV_AD_TYPE_FIELD_SIZE))
{
return NRF_ERROR_DATA_SIZE;
}
// Encode Length and AD Type.
p_encoded_data[*p_offset] = (uint8_t)(ADV_AD_TYPE_FIELD_SIZE + data_size);
*p_offset += ADV_LENGTH_FIELD_SIZE;
p_encoded_data[*p_offset] = BLE_GAP_AD_TYPE_SERVICE_DATA;
*p_offset += ADV_AD_TYPE_FIELD_SIZE;
// Encode service 16-bit UUID.
*p_offset += uint16_encode(p_service_data->service_uuid, &p_encoded_data[*p_offset]);
// Encode additional service data.
if (p_service_data->data.size > 0)
{
if (p_service_data->data.p_data == NULL)
{
return NRF_ERROR_INVALID_PARAM;
}
memcpy(&p_encoded_data[*p_offset], p_service_data->data.p_data, p_service_data->data.size);
*p_offset += p_service_data->data.size;
}
}
return NRF_SUCCESS;
}
uint32_t adv_data_encode(ble_advdata_t const * const p_advdata,
uint8_t * const p_encoded_data,
uint16_t * const p_len)
{
uint32_t err_code = NRF_SUCCESS;
uint16_t max_size = *p_len;
*p_len = 0;
//Encode Security Manager OOB Flags
if (p_advdata->p_sec_mgr_oob_flags != NULL)
{
err_code = sec_mgr_oob_flags_encode(*p_advdata->p_sec_mgr_oob_flags,
p_encoded_data,
p_len,
max_size);
VERIFY_SUCCESS(err_code);
}
// Encode Security Manager TK value
if (NULL != p_advdata->p_tk_value)
{
err_code = tk_value_encode(p_advdata->p_tk_value, p_encoded_data, p_len, max_size);
VERIFY_SUCCESS(err_code);
}
// Encode LE Role
if (BLE_ADVDATA_ROLE_NOT_PRESENT != p_advdata->le_role)
{
err_code = le_role_encode(p_advdata->le_role, p_encoded_data, p_len, max_size);
VERIFY_SUCCESS(err_code);
}
// Encode LE Bluetooth Device Address
if (p_advdata->include_ble_device_addr)
{
err_code = ble_device_addr_encode(p_encoded_data, p_len, max_size);
VERIFY_SUCCESS(err_code);
}
// Encode appearance.
if (p_advdata->include_appearance)
{
err_code = appearance_encode(p_encoded_data, p_len, max_size);
VERIFY_SUCCESS(err_code);
}
//Encode Flags
if(p_advdata->flags != 0 )
{
err_code = flags_encode(p_advdata->flags, p_encoded_data, p_len, max_size);
VERIFY_SUCCESS(err_code);
}
// Encode TX power level.
if (p_advdata->p_tx_power_level != NULL)
{
err_code = tx_power_level_encode(*p_advdata->p_tx_power_level,
p_encoded_data,
p_len,
max_size);
VERIFY_SUCCESS(err_code);
}
// Encode 'more available' uuid list.
if (p_advdata->uuids_more_available.uuid_cnt > 0)
{
err_code = uuid_list_encode(&p_advdata->uuids_more_available,
BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_MORE_AVAILABLE,
BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE,
p_encoded_data,
p_len,
max_size);
VERIFY_SUCCESS(err_code);
}
// Encode 'complete' uuid list.
if (p_advdata->uuids_complete.uuid_cnt > 0)
{
err_code = uuid_list_encode(&p_advdata->uuids_complete,
BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE,
BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE,
p_encoded_data,
p_len,
max_size);
VERIFY_SUCCESS(err_code);
}
// Encode 'solicited service' uuid list.
if (p_advdata->uuids_solicited.uuid_cnt > 0)
{
err_code = uuid_list_encode(&p_advdata->uuids_solicited,
BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_16BIT,
BLE_GAP_AD_TYPE_SOLICITED_SERVICE_UUIDS_128BIT,
p_encoded_data,
p_len,
max_size);
VERIFY_SUCCESS(err_code);
}
// Encode Slave Connection Interval Range.
if (p_advdata->p_slave_conn_int != NULL)
{
err_code = conn_int_encode(p_advdata->p_slave_conn_int, p_encoded_data, p_len, max_size);
VERIFY_SUCCESS(err_code);
}
// Encode Manufacturer Specific Data.
if (p_advdata->p_manuf_specific_data != NULL)
{
err_code = manuf_specific_data_encode(p_advdata->p_manuf_specific_data,
p_encoded_data,
p_len,
max_size);
VERIFY_SUCCESS(err_code);
}
// Encode Service Data.
if (p_advdata->service_data_count > 0)
{
err_code = service_data_encode(p_advdata, p_encoded_data, p_len, max_size);
VERIFY_SUCCESS(err_code);
}
// Encode name. WARNING: it is encoded last on purpose since too long device name is truncated.
if (p_advdata->name_type != BLE_ADVDATA_NO_NAME)
{
err_code = name_encode(p_advdata, p_encoded_data, p_len, max_size);
VERIFY_SUCCESS(err_code);
}
return err_code;
}
static uint32_t advdata_check(const ble_advdata_t * p_advdata)
{
// Flags must be included in advertising data, and the BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED flag must be set.
if (
((p_advdata->flags & BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED) == 0)
)
{
return NRF_ERROR_INVALID_PARAM;
}
return NRF_SUCCESS;
}
static uint32_t srdata_check(const ble_advdata_t * p_srdata)
{
// Flags shall not be included in the scan response data.
if (p_srdata->flags)
{
return NRF_ERROR_INVALID_PARAM;
}
return NRF_SUCCESS;
}
uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t * p_srdata)
{
uint32_t err_code;
uint16_t len_advdata = BLE_GAP_ADV_MAX_SIZE;
uint16_t len_srdata = BLE_GAP_ADV_MAX_SIZE;
uint8_t encoded_advdata[BLE_GAP_ADV_MAX_SIZE];
uint8_t encoded_srdata[BLE_GAP_ADV_MAX_SIZE];
uint8_t * p_encoded_advdata;
uint8_t * p_encoded_srdata;
// Encode advertising data (if supplied).
if (p_advdata != NULL)
{
err_code = advdata_check(p_advdata);
VERIFY_SUCCESS(err_code);
err_code = adv_data_encode(p_advdata, encoded_advdata, &len_advdata);
VERIFY_SUCCESS(err_code);
p_encoded_advdata = encoded_advdata;
}
else
{
p_encoded_advdata = NULL;
len_advdata = 0;
}
// Encode scan response data (if supplied).
if (p_srdata != NULL)
{
err_code = srdata_check(p_srdata);
VERIFY_SUCCESS(err_code);
err_code = adv_data_encode(p_srdata, encoded_srdata, &len_srdata);
VERIFY_SUCCESS(err_code);
p_encoded_srdata = encoded_srdata;
}
else
{
p_encoded_srdata = NULL;
len_srdata = 0;
}
// Pass encoded advertising data and/or scan response data to the stack.
return sd_ble_gap_adv_data_set(p_encoded_advdata, len_advdata, p_encoded_srdata, len_srdata);
}

View File

@ -1,239 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** @file
*
* @defgroup ble_sdk_lib_advdata Advertising and Scan Response Data Encoder
* @{
* @ingroup ble_sdk_lib
* @brief Functions for encoding data in the Advertising and Scan Response Data format,
* and for passing the data to the stack.
*/
#ifndef BLE_ADVDATA_H__
#define BLE_ADVDATA_H__
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "nrf_ble.h"
#include "app_util.h"
#define ADV_LENGTH_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the length. */
#define ADV_AD_TYPE_FIELD_SIZE 1UL /**< Advertising Data and Scan Response format contains 1 octet for the AD type. */
#define ADV_AD_DATA_OFFSET (ADV_LENGTH_FIELD_SIZE + \
ADV_AD_TYPE_FIELD_SIZE) /**< Offset for the AD data field of the Advertising Data and Scan Response format. */
#define AD_TYPE_TK_VALUE_DATA_SIZE (sizeof(ble_advdata_tk_value_t)) /**< Data size (in octets) of the Security Manager TK value AD type. */
#define AD_TYPE_TK_VALUE_SIZE (ADV_AD_DATA_OFFSET + \
AD_TYPE_TK_VALUE_DATA_SIZE) /**< Size (in octets) of the Security Manager TK value AD type. */
#define AD_TYPE_LE_ROLE_DATA_SIZE 1UL /**< Data size (in octets) of the LE Bluetooth Device Address AD type. */
#define AD_TYPE_LE_ROLE_SIZE (ADV_AD_DATA_OFFSET + \
AD_TYPE_LE_ROLE_DATA_SIZE) /**< Size (in octets) of the LE Bluetooth Device Address AD type. */
#define AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE 1UL /**< Data size (in octets) of the Address type of the LE Bluetooth Device Address AD type. */
#define AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE (BLE_GAP_ADDR_LEN + \
AD_TYPE_BLE_DEVICE_ADDR_TYPE_SIZE) /**< Data size (in octets) of the LE Bluetooth Device Address AD type. */
#define AD_TYPE_BLE_DEVICE_ADDR_SIZE (ADV_AD_DATA_OFFSET + \
AD_TYPE_BLE_DEVICE_ADDR_DATA_SIZE) /**< Size (in octets) of the LE Bluetooth Device Address AD type. */
#define AD_TYPE_APPEARANCE_DATA_SIZE 2UL /**< Data size (in octets) of the Appearance AD type. */
#define AD_TYPE_APPEARANCE_SIZE (ADV_AD_DATA_OFFSET + \
AD_TYPE_APPEARANCE_DATA_SIZE) /**< Size (in octets) of the Appearance AD type. */
#define AD_TYPE_FLAGS_DATA_SIZE 1UL /**< Data size (in octets) of the Flags AD type. */
#define AD_TYPE_FLAGS_SIZE (ADV_AD_DATA_OFFSET + \
AD_TYPE_FLAGS_DATA_SIZE) /**< Size (in octets) of the Flags AD type. */
#define AD_TYPE_TX_POWER_LEVEL_DATA_SIZE 1UL /**< Data size (in octets) of the TX Power Level AD type. */
#define AD_TYPE_TX_POWER_LEVEL_SIZE (ADV_AD_DATA_OFFSET + \
AD_TYPE_TX_POWER_LEVEL_DATA_SIZE) /**< Size (in octets) of the TX Power Level AD type. */
#define AD_TYPE_CONN_INT_DATA_SIZE 4UL /**< Data size (in octets) of the Slave Connection Interval Range AD type. */
#define AD_TYPE_CONN_INT_SIZE (ADV_AD_DATA_OFFSET + \
AD_TYPE_CONN_INT_DATA_SIZE) /**< Data size (in octets) of the Slave Connection Interval Range AD type. */
#define AD_TYPE_MANUF_SPEC_DATA_ID_SIZE 2UL /**< Size (in octets) of the Company Identifier Code, which is a part of the Manufacturer Specific Data AD type. */
#define AD_TYPE_SERV_DATA_16BIT_UUID_SIZE 2UL /**< Size (in octets) of the 16-bit UUID, which is a part of the Service Data AD type. */
#define AD_TYPE_OOB_FLAGS_DATA_SIZE 1UL /**< Data size (in octets) of the Security Manager OOB Flags AD type. */
#define AD_TYPE_OOB_FLAGS_SIZE (ADV_AD_DATA_OFFSET + \
AD_TYPE_OOB_FLAGS_DATA_SIZE) /**< Size (in octets) of the Security Manager OOB Flags AD type. */
#define AD_TYPE_SEC_MGR_OOB_FLAG_SET 1U /**< Security Manager OOB Flag set. Flag selection is done using _POS defines */
#define AD_TYPE_SEC_MGR_OOB_FLAG_CLEAR 0U /**< Security Manager OOB Flag clear. Flag selection is done using _POS defines */
#define AD_TYPE_SEC_MGR_OOB_FLAG_OOB_DATA_PRESENT_POS 0UL /**< Security Manager OOB Data Present Flag position. */
#define AD_TYPE_SEC_MGR_OOB_FLAG_OOB_LE_SUPPORTED_POS 1UL /**< Security Manager OOB Low Energy Supported Flag position. */
#define AD_TYPE_SEC_MGR_OOB_FLAG_SIM_LE_AND_EP_POS 2UL /**< Security Manager OOB Simultaneous LE and BR/EDR to Same Device Capable Flag position. */
#define AD_TYPE_SEC_MGR_OOB_ADDRESS_TYPE_PUBLIC 0UL /**< Security Manager OOB Public Address type. */
#define AD_TYPE_SEC_MGR_OOB_ADDRESS_TYPE_RANDOM 1UL /**< Security Manager OOB Random Address type. */
#define AD_TYPE_SEC_MGR_OOB_FLAG_ADDRESS_TYPE_POS 3UL /**< Security Manager OOB Address type Flag (0 = Public Address, 1 = Random Address) position. */
/**@brief Security Manager TK value. */
typedef struct
{
uint8_t tk[BLE_GAP_SEC_KEY_LEN]; /**< Array containing TK value. */
} ble_advdata_tk_value_t;
/**@brief Advertising data LE Role types. This enumeration contains the options available for the LE role inside
* the advertising data. */
typedef enum
{
BLE_ADVDATA_ROLE_NOT_PRESENT = 0, /**< LE Role AD structure not present. */
BLE_ADVDATA_ROLE_ONLY_PERIPH, /**< Only Peripheral Role supported. */
BLE_ADVDATA_ROLE_ONLY_CENTRAL, /**< Only Central Role supported. */
BLE_ADVDATA_ROLE_BOTH_PERIPH_PREFERRED, /**< Peripheral and Central Role supported. Peripheral Role preferred for connection establishment. */
BLE_ADVDATA_ROLE_BOTH_CENTRAL_PREFERRED /**< Peripheral and Central Role supported. Central Role preferred for connection establishment */
} ble_advdata_le_role_t;
/**@brief Advertising data name type. This enumeration contains the options available for the device name inside
* the advertising data. */
typedef enum
{
BLE_ADVDATA_NO_NAME, /**< Include no device name in advertising data. */
BLE_ADVDATA_SHORT_NAME, /**< Include short device name in advertising data. */
BLE_ADVDATA_FULL_NAME /**< Include full device name in advertising data. */
} ble_advdata_name_type_t;
/**@brief UUID list type. */
typedef struct
{
uint16_t uuid_cnt; /**< Number of UUID entries. */
ble_uuid_t * p_uuids; /**< Pointer to UUID array entries. */
} ble_advdata_uuid_list_t;
/**@brief Connection interval range structure. */
typedef struct
{
uint16_t min_conn_interval; /**< Minimum connection interval, in units of 1.25 ms, range 6 to 3200 (7.5 ms to 4 s). */
uint16_t max_conn_interval; /**< Maximum connection interval, in units of 1.25 ms, range 6 to 3200 (7.5 ms to 4 s). The value 0xFFFF indicates no specific maximum. */
} ble_advdata_conn_int_t;
/**@brief Manufacturer specific data structure. */
typedef struct
{
uint16_t company_identifier; /**< Company identifier code. */
uint8_array_t data; /**< Additional manufacturer specific data. */
} ble_advdata_manuf_data_t;
/**@brief Service data structure. */
typedef struct
{
uint16_t service_uuid; /**< Service UUID. */
uint8_array_t data; /**< Additional service data. */
} ble_advdata_service_data_t;
/**@brief Advertising data structure. This structure contains all options and data needed for encoding and
* setting the advertising data. */
typedef struct
{
ble_advdata_name_type_t name_type; /**< Type of device name. */
uint8_t short_name_len; /**< Length of short device name (if short type is specified). */
bool include_appearance; /**< Determines if Appearance shall be included. */
uint8_t flags; /**< Advertising data Flags field. */
int8_t * p_tx_power_level; /**< TX Power Level field. */
ble_advdata_uuid_list_t uuids_more_available; /**< List of UUIDs in the 'More Available' list. */
ble_advdata_uuid_list_t uuids_complete; /**< List of UUIDs in the 'Complete' list. */
ble_advdata_uuid_list_t uuids_solicited; /**< List of solicited UUIDs. */
ble_advdata_conn_int_t * p_slave_conn_int; /**< Slave Connection Interval Range. */
ble_advdata_manuf_data_t * p_manuf_specific_data; /**< Manufacturer specific data. */
ble_advdata_service_data_t * p_service_data_array; /**< Array of Service data structures. */
uint8_t service_data_count; /**< Number of Service data structures. */
bool include_ble_device_addr; /**< Determines if LE Bluetooth Device Address shall be included. */
ble_advdata_le_role_t le_role; /**< LE Role field. Included when different from @ref BLE_ADVDATA_ROLE_NOT_PRESENT. @warning This field can be used only for NFC. For BLE advertising, set it to NULL. */
ble_advdata_tk_value_t * p_tk_value; /**< Security Manager TK value field. Included when different from NULL. @warning This field can be used only for NFC. For BLE advertising, set it to NULL.*/
uint8_t * p_sec_mgr_oob_flags; /**< Security Manager Out Of Band Flags field. Included when different from NULL. @warning This field can be used only for NFC. For BLE advertising, set it to NULL.*/
} ble_advdata_t;
/**@brief Function for encoding data in the Advertising and Scan Response data format
* (AD structures).
*
* @details This function encodes data into the Advertising and Scan Response data format
* (AD structures) based on the selections in the supplied structures. This function can be used to
* create a payload of Advertising packet or Scan Response packet, or a payload of NFC
* message intended for initiating the Out-of-Band pairing.
*
* @param[in] p_advdata Pointer to the structure for specifying the content of encoded data.
* @param[out] p_encoded_data Pointer to the buffer where encoded data will be returned.
* @param[in,out] p_len \c in: Size of \p p_encoded_data buffer.
* \c out: Length of encoded data.
*
* @retval NRF_SUCCESS If the operation was successful.
* @retval NRF_ERROR_INVALID_PARAM If the operation failed because a wrong parameter was provided in \p p_advdata.
* @retval NRF_ERROR_DATA_SIZE If the operation failed because not all the requested data could fit into the
* provided buffer or some encoded AD structure is too long and its
* length cannot be encoded with one octet.
*
* @warning This API may override the application's request to use the long name and use a short name
* instead. This truncation will occur in case the long name does not fit the provided buffer size.
* The application can specify a preferred short name length if truncation is required.
* For example, if the complete device name is ABCD_HRMonitor, the application can specify the short name
* length to be 8, so that the short device name appears as ABCD_HRM instead of ABCD_HRMo or ABCD_HRMoni
* if the available size for the short name is 9 or 12 respectively, to have a more appropriate short name.
* However, it should be noted that this is just a preference that the application can specify, and
* if the preference is too large to fit in the provided buffer, the name can be truncated further.
*/
uint32_t adv_data_encode(ble_advdata_t const * const p_advdata,
uint8_t * const p_encoded_data,
uint16_t * const p_len);
/**@brief Function for encoding and setting the advertising data and/or scan response data.
*
* @details This function encodes advertising data and/or scan response data based on the selections
* in the supplied structures, and passes the encoded data to the stack.
*
* @param[in] p_advdata Structure for specifying the content of the advertising data.
* Set to NULL if advertising data is not to be set.
* @param[in] p_srdata Structure for specifying the content of the scan response data.
* Set to NULL if scan response data is not to be set.
*
* @retval NRF_SUCCESS If the operation was successful.
* @retval NRF_ERROR_INVALID_PARAM If the operation failed because a wrong parameter was provided in \p p_advdata.
* @retval NRF_ERROR_DATA_SIZE If the operation failed because not all the requested data could fit into the
* advertising packet. The maximum size of the advertisement packet
* is @ref BLE_GAP_ADV_MAX_SIZE.
*
* @warning This API may override the application's request to use the long name and use a short name
* instead. This truncation will occur in case the long name does not fit the provided buffer size.
* The application can specify a preferred short name length if truncation is required.
* For example, if the complete device name is ABCD_HRMonitor, the application can specify the short name
* length to be 8, so that the short device name appears as ABCD_HRM instead of ABCD_HRMo or ABCD_HRMoni
* if the available size for the short name is 9 or 12 respectively, to have a more appropriate short name.
* However, it should be noted that this is just a preference that the application can specify, and
* if the preference is too large to fit in the provided buffer, the name can be truncated further.
*/
uint32_t ble_advdata_set(const ble_advdata_t * p_advdata, const ble_advdata_t * p_srdata);
#endif // BLE_ADVDATA_H__
/** @} */

View File

@ -1,138 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** @file
*
* @defgroup ble_sdk_lib_conn_params Connection Parameters Negotiation
* @{
* @ingroup ble_sdk_lib
* @brief Module for initiating and executing a connection parameters negotiation procedure.
*/
#ifndef BLE_CONN_PARAMS_H__
#define BLE_CONN_PARAMS_H__
#include <stdint.h>
#include "nrf_ble.h"
#include "ble_srv_common.h"
/**@brief Connection Parameters Module event type. */
typedef enum
{
BLE_CONN_PARAMS_EVT_FAILED , /**< Negotiation procedure failed. */
BLE_CONN_PARAMS_EVT_SUCCEEDED /**< Negotiation procedure succeeded. */
} ble_conn_params_evt_type_t;
/**@brief Connection Parameters Module event. */
typedef struct
{
ble_conn_params_evt_type_t evt_type; /**< Type of event. */
} ble_conn_params_evt_t;
/**@brief Connection Parameters Module event handler type. */
typedef void (*ble_conn_params_evt_handler_t) (ble_conn_params_evt_t * p_evt);
/**@brief Connection Parameters Module init structure. This contains all options and data needed for
* initialization of the connection parameters negotiation module. */
typedef struct
{
ble_gap_conn_params_t * p_conn_params; /**< Pointer to the connection parameters desired by the application. When calling ble_conn_params_init, if this parameter is set to NULL, the connection parameters will be fetched from host. */
uint32_t first_conn_params_update_delay; /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (in number of timer ticks). */
uint32_t next_conn_params_update_delay; /**< Time between each call to sd_ble_gap_conn_param_update after the first (in number of timer ticks). Recommended value 30 seconds as per BLUETOOTH SPECIFICATION Version 4.0. */
uint8_t max_conn_params_update_count; /**< Number of attempts before giving up the negotiation. */
uint16_t start_on_notify_cccd_handle; /**< If procedure is to be started when notification is started, set this to the handle of the corresponding CCCD. Set to BLE_GATT_HANDLE_INVALID if procedure is to be started on connect event. */
bool disconnect_on_fail; /**< Set to TRUE if a failed connection parameters update shall cause an automatic disconnection, set to FALSE otherwise. */
ble_conn_params_evt_handler_t evt_handler; /**< Event handler to be called for handling events in the Connection Parameters. */
ble_srv_error_handler_t error_handler; /**< Function to be called in case of an error. */
} ble_conn_params_init_t;
/**@brief Function for initializing the Connection Parameters module.
*
* @note If the negotiation procedure should be triggered when notification/indication of
* any characteristic is enabled by the peer, then this function must be called after
* having initialized the services.
*
* @param[in] p_init This contains information needed to initialize this module.
*
* @return NRF_SUCCESS on successful initialization, otherwise an error code.
*/
uint32_t ble_conn_params_init(const ble_conn_params_init_t * p_init);
/**@brief Function for stopping the Connection Parameters module.
*
* @details This function is intended to be used by the application to clean up the connection
* parameters update module. This will stop the connection parameters update timer if
* running, thereby preventing any impending connection parameters update procedure. This
* function must be called by the application when it needs to clean itself up (for
* example, before disabling the bluetooth SoftDevice) so that an unwanted timer expiry
* event can be avoided.
*
* @return NRF_SUCCESS on successful initialization, otherwise an error code.
*/
uint32_t ble_conn_params_stop(void);
/**@brief Function for changing the current connection parameters to a new set.
*
* @details Use this function to change the connection parameters to a new set of parameter
* (ie different from the ones given at init of the module).
* This function is usefull for scenario where most of the time the application
* needs a relatively big connection interval, and just sometimes, for a temporary
* period requires shorter connection interval, for example to transfer a higher
* amount of data.
* If the given parameters does not match the current connection's parameters
* this function initiates a new negotiation.
*
* @param[in] new_params This contains the new connections parameters to setup.
*
* @return NRF_SUCCESS on successful initialization, otherwise an error code.
*/
uint32_t ble_conn_params_change_conn_params(ble_gap_conn_params_t *new_params);
/**@brief Function for handling the Application's BLE Stack events.
*
* @details Handles all events from the BLE stack that are of interest to this module.
*
* @param[in] p_ble_evt The event received from the BLE stack.
*/
void ble_conn_params_on_ble_evt(ble_evt_t * p_ble_evt);
#endif // BLE_CONN_PARAMS_H__
/** @} */

View File

@ -1,414 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "ble_conn_state.h"
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "nrf_ble.h"
#include "sdk_mapped_flags.h"
#include "app_error.h"
#if defined(__CC_ARM)
#pragma push
#pragma anon_unions
#elif defined(__ICCARM__)
#pragma language=extended
#elif defined(__GNUC__)
/* anonymous unions are enabled by default */
#endif
#define BLE_CONN_STATE_N_DEFAULT_FLAGS 5 /**< The number of flags kept for each connection, excluding user flags. */
#define BLE_CONN_STATE_N_FLAGS (BLE_CONN_STATE_N_DEFAULT_FLAGS + BLE_CONN_STATE_N_USER_FLAGS) /**< The number of flags kept for each connection, including user flags. */
/**@brief Structure containing all the flag collections maintained by the Connection State module.
*/
typedef struct
{
sdk_mapped_flags_t valid_flags; /**< Flags indicating which connection handles are valid. */
sdk_mapped_flags_t connected_flags; /**< Flags indicating which connections are connected, since disconnected connection handles will not immediately be invalidated. */
sdk_mapped_flags_t central_flags; /**< Flags indicating in which connections the local device is the central. */
sdk_mapped_flags_t encrypted_flags; /**< Flags indicating which connections are encrypted. */
sdk_mapped_flags_t mitm_protected_flags; /**< Flags indicating which connections have encryption with protection from man-in-the-middle attacks. */
sdk_mapped_flags_t user_flags[BLE_CONN_STATE_N_USER_FLAGS]; /**< Flags that can be reserved by the user. The flags will be cleared when a connection is invalidated, otherwise, the user is wholly responsible for the flag states. */
} ble_conn_state_flag_collections_t;
/**@brief Structure containing the internal state of the Connection State module.
*/
typedef struct
{
uint32_t acquired_flags; /**< Bitmap for keeping track of which user flags have been acquired. */
uint16_t valid_conn_handles[SDK_MAPPED_FLAGS_N_KEYS]; /**< List of connection handles used as keys for the sdk_mapped_flags module. */
union
{
ble_conn_state_flag_collections_t flags; /**< Flag collections kept by the Connection State module. */
sdk_mapped_flags_t flag_array[BLE_CONN_STATE_N_FLAGS]; /**< Flag collections as array to allow use of @ref sdk_mapped_flags_bulk_update_by_key() when setting all flags. */
};
} ble_conn_state_t;
#if defined(__CC_ARM)
#pragma pop
#elif defined(__ICCARM__)
/* leave anonymous unions enabled */
#elif defined(__GNUC__)
/* anonymous unions are enabled by default */
#endif
static ble_conn_state_t m_bcs = {0}; /**< Instantiation of the internal state. */
/**@brief Function for resetting all internal memory to the values it had at initialization.
*/
void bcs_internal_state_reset(void)
{
memset( &m_bcs, 0, sizeof(ble_conn_state_t) );
}
/**@brief Function for activating a connection record.
*
* @param p_record The record to activate.
* @param conn_handle The connection handle to copy into the record.
* @param role The role of the connection.
*
* @return whether the record was activated successfully.
*/
static bool record_activate(uint16_t conn_handle)
{
uint16_t available_index = sdk_mapped_flags_first_key_index_get(~m_bcs.flags.valid_flags);
if (available_index != SDK_MAPPED_FLAGS_INVALID_INDEX)
{
m_bcs.valid_conn_handles[available_index] = conn_handle;
sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles,
&m_bcs.flags.connected_flags,
conn_handle,
1);
sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles,
&m_bcs.flags.valid_flags,
conn_handle,
1);
return true;
}
return false;
}
/**@brief Function for marking a connection record as invalid and resetting the values.
*
* @param p_record The record to invalidate.
*/
static void record_invalidate(uint16_t conn_handle)
{
sdk_mapped_flags_bulk_update_by_key(m_bcs.valid_conn_handles,
m_bcs.flag_array,
BLE_CONN_STATE_N_FLAGS,
conn_handle,
0);
}
/**@brief Function for marking a connection as disconnected. See @ref BLE_CONN_STATUS_DISCONNECTED.
*
* @param p_record The record of the connection to set as disconnected.
*/
static void record_set_disconnected(uint16_t conn_handle)
{
sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles,
&m_bcs.flags.connected_flags,
conn_handle,
0);
}
/**@brief Function for invalidating records with a @ref BLE_CONN_STATUS_DISCONNECTED
* connection status
*/
static void record_purge_disconnected()
{
sdk_mapped_flags_key_list_t disconnected_list;
disconnected_list = sdk_mapped_flags_key_list_get(
m_bcs.valid_conn_handles,
(~m_bcs.flags.connected_flags) & (m_bcs.flags.valid_flags));
for (uint32_t i = 0; i < disconnected_list.len; i++)
{
record_invalidate(disconnected_list.flag_keys[i]);
}
}
/**@brief Function for checking if a user flag has been acquired.
*
* @param[in] flag_id Which flag to check.
*
* @return Whether the flag has been acquired.
*/
static bool user_flag_is_acquired(ble_conn_state_user_flag_id_t flag_id)
{
return ((m_bcs.acquired_flags & (1 << flag_id)) != 0);
}
/**@brief Function for marking a user flag as acquired.
*
* @param[in] flag_id Which flag to mark.
*/
static void user_flag_acquire(ble_conn_state_user_flag_id_t flag_id)
{
m_bcs.acquired_flags |= (1 << flag_id);
}
void ble_conn_state_init(void)
{
bcs_internal_state_reset();
}
void ble_conn_state_on_ble_evt(ble_evt_t * p_ble_evt)
{
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
record_purge_disconnected();
if ( !record_activate(p_ble_evt->evt.gap_evt.conn_handle) )
{
// No more records available. Should not happen.
APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
}
else
{
bool is_central =
(p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_CENTRAL);
sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles,
&m_bcs.flags.central_flags,
p_ble_evt->evt.gap_evt.conn_handle,
is_central);
}
break;
case BLE_GAP_EVT_DISCONNECTED:
record_set_disconnected(p_ble_evt->evt.gap_evt.conn_handle);
break;
case BLE_GAP_EVT_CONN_SEC_UPDATE:
sdk_mapped_flags_update_by_key(
m_bcs.valid_conn_handles,
&m_bcs.flags.encrypted_flags,
p_ble_evt->evt.gap_evt.conn_handle,
(p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv > 1));
sdk_mapped_flags_update_by_key(
m_bcs.valid_conn_handles,
&m_bcs.flags.mitm_protected_flags,
p_ble_evt->evt.gap_evt.conn_handle,
(p_ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec.sec_mode.lv > 2));
break;
}
}
bool ble_conn_state_valid(uint16_t conn_handle)
{
return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
m_bcs.flags.valid_flags,
conn_handle);
}
uint8_t ble_conn_state_role(uint16_t conn_handle)
{
uint8_t role = BLE_GAP_ROLE_INVALID;
if ( sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles, m_bcs.flags.valid_flags, conn_handle) )
{
bool central = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
m_bcs.flags.central_flags,
conn_handle);
role = central ? BLE_GAP_ROLE_CENTRAL : BLE_GAP_ROLE_PERIPH;
}
return role;
}
ble_conn_state_status_t ble_conn_state_status(uint16_t conn_handle)
{
ble_conn_state_status_t conn_status = BLE_CONN_STATUS_INVALID;
bool valid = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
m_bcs.flags.valid_flags,
conn_handle);
if (valid)
{
bool connected = sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
m_bcs.flags.connected_flags,
conn_handle);
conn_status = connected ? BLE_CONN_STATUS_CONNECTED : BLE_CONN_STATUS_DISCONNECTED;
}
return conn_status;
}
bool ble_conn_state_encrypted(uint16_t conn_handle)
{
return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
m_bcs.flags.encrypted_flags,
conn_handle);
}
bool ble_conn_state_mitm_protected(uint16_t conn_handle)
{
return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
m_bcs.flags.mitm_protected_flags,
conn_handle);
}
uint32_t ble_conn_state_n_connections(void)
{
return sdk_mapped_flags_n_flags_set(m_bcs.flags.connected_flags);
}
uint32_t ble_conn_state_n_centrals(void)
{
return sdk_mapped_flags_n_flags_set((m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags));
}
uint32_t ble_conn_state_n_peripherals(void)
{
return sdk_mapped_flags_n_flags_set((~m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags));
}
sdk_mapped_flags_key_list_t ble_conn_state_conn_handles(void)
{
return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles, m_bcs.flags.valid_flags);
}
sdk_mapped_flags_key_list_t ble_conn_state_central_handles(void)
{
return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles,
(m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags));
}
sdk_mapped_flags_key_list_t ble_conn_state_periph_handles(void)
{
return sdk_mapped_flags_key_list_get(m_bcs.valid_conn_handles,
(~m_bcs.flags.central_flags) & (m_bcs.flags.connected_flags));
}
ble_conn_state_user_flag_id_t ble_conn_state_user_flag_acquire(void)
{
for (ble_conn_state_user_flag_id_t i = BLE_CONN_STATE_USER_FLAG0;
i < BLE_CONN_STATE_N_USER_FLAGS;
i++)
{
if ( !user_flag_is_acquired(i) )
{
user_flag_acquire(i);
return i;
}
}
return BLE_CONN_STATE_USER_FLAG_INVALID;
}
bool ble_conn_state_user_flag_get(uint16_t conn_handle, ble_conn_state_user_flag_id_t flag_id)
{
if (user_flag_is_acquired(flag_id))
{
return sdk_mapped_flags_get_by_key(m_bcs.valid_conn_handles,
m_bcs.flags.user_flags[flag_id],
conn_handle);
}
else
{
return false;
}
}
void ble_conn_state_user_flag_set(uint16_t conn_handle,
ble_conn_state_user_flag_id_t flag_id,
bool value)
{
if (user_flag_is_acquired(flag_id))
{
sdk_mapped_flags_update_by_key(m_bcs.valid_conn_handles,
&m_bcs.flags.user_flags[flag_id],
conn_handle,
value);
}
}
sdk_mapped_flags_t ble_conn_state_user_flag_collection(ble_conn_state_user_flag_id_t flag_id)
{
if ( user_flag_is_acquired(flag_id) )
{
return m_bcs.flags.user_flags[flag_id];
}
else
{
return 0;
}
}

View File

@ -1,302 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* @file
*
* @defgroup ble_conn_state Connection state
* @ingroup ble_sdk_lib
* @{
* @brief Module for storing data on BLE connections.
*
* @details This module stores certain states for each connection, which can be queried by
* connection handle. The module uses BLE events to keep the states updated.
*
* In addition to the preprogrammed states, this module can also keep track of a number of
* binary user states, or <i>user flags</i>. These are reset to 0 for new connections, but
* otherwise not touched by this module.
*
* This module uses the @ref sdk_mapped_flags module, with connection handles as keys and
* the connection states as flags.
*
* @note A connection handle is not immediately invalidated when it is disconnected. Certain states,
* such as the role, can still be queried until the next time a new connection is established
* to any device.
*
* To function properly, this module must be provided with BLE events from the SoftDevice
* through the @ref ble_conn_state_on_ble_evt() function. This module should be the first
* to receive BLE events if they are dispatched to multiple modules.
*/
#ifndef BLE_CONN_STATE_H__
#define BLE_CONN_STATE_H__
#include <stdbool.h>
#include <stdint.h>
#include "nrf_ble.h"
#include "sdk_mapped_flags.h"
/**@brief Connection handle statuses.
*/
typedef enum
{
BLE_CONN_STATUS_INVALID, /**< The connection handle is invalid. */
BLE_CONN_STATUS_DISCONNECTED, /**< The connection handle refers to a connection that has been disconnected, but not yet invalidated. */
BLE_CONN_STATUS_CONNECTED, /**< The connection handle refers to an active connection. */
} ble_conn_state_status_t;
#define BLE_CONN_STATE_N_USER_FLAGS 24 /**< The number of available user flags. */
/**@brief One ID for each user flag collection.
*
* @details These IDs are used to identify user flag collections in the API calls.
*/
typedef enum
{
BLE_CONN_STATE_USER_FLAG0 = 0,
BLE_CONN_STATE_USER_FLAG1,
BLE_CONN_STATE_USER_FLAG2,
BLE_CONN_STATE_USER_FLAG3,
BLE_CONN_STATE_USER_FLAG4,
BLE_CONN_STATE_USER_FLAG5,
BLE_CONN_STATE_USER_FLAG6,
BLE_CONN_STATE_USER_FLAG7,
BLE_CONN_STATE_USER_FLAG8,
BLE_CONN_STATE_USER_FLAG9,
BLE_CONN_STATE_USER_FLAG10,
BLE_CONN_STATE_USER_FLAG11,
BLE_CONN_STATE_USER_FLAG12,
BLE_CONN_STATE_USER_FLAG13,
BLE_CONN_STATE_USER_FLAG14,
BLE_CONN_STATE_USER_FLAG15,
BLE_CONN_STATE_USER_FLAG16,
BLE_CONN_STATE_USER_FLAG17,
BLE_CONN_STATE_USER_FLAG18,
BLE_CONN_STATE_USER_FLAG19,
BLE_CONN_STATE_USER_FLAG20,
BLE_CONN_STATE_USER_FLAG21,
BLE_CONN_STATE_USER_FLAG22,
BLE_CONN_STATE_USER_FLAG23,
BLE_CONN_STATE_USER_FLAG_INVALID,
} ble_conn_state_user_flag_id_t;
/**
* @defgroup ble_conn_state_functions BLE connection state functions
* @{
*/
/**@brief Function for initializing or resetting the module.
*
* @details This function sets all states to their default, removing all records of connection handles.
*/
void ble_conn_state_init(void);
/**@brief Function for providing BLE SoftDevice events to the connection state module.
*
* @param[in] p_ble_evt The SoftDevice event.
*/
void ble_conn_state_on_ble_evt(ble_evt_t * p_ble_evt);
/**@brief Function for querying whether a connection handle represents a valid connection.
*
* @details A connection might be valid and have a BLE_CONN_STATUS_DISCONNECTED status.
* Those connections are invalidated after a new connection occurs.
*
* @param[in] conn_handle Handle of the connection.
*
* @retval true If conn_handle represents a valid connection, thus a connection for which
we have a record.
* @retval false If conn_handle is @ref BLE_GAP_ROLE_INVALID, or if it has never been recorded.
*/
bool ble_conn_state_valid(uint16_t conn_handle);
/**@brief Function for querying the role of the local device in a connection.
*
* @param[in] conn_handle Handle of the connection to get the role for.
*
* @return The role of the local device in the connection (see @ref BLE_GAP_ROLES).
* If conn_handle is not valid, the function returns BLE_GAP_ROLE_INVALID.
*/
uint8_t ble_conn_state_role(uint16_t conn_handle);
/**@brief Function for querying the status of a connection.
*
* @param[in] conn_handle Handle of the connection.
*
* @return The status of the connection.
* If conn_handle is not valid, the function returns BLE_CONN_STATE_INVALID.
*/
ble_conn_state_status_t ble_conn_state_status(uint16_t conn_handle);
/**@brief Function for querying whether a connection is encrypted.
*
* @param[in] conn_handle Handle of connection to get the encryption state for.
*
* @retval true If the connection is encrypted.
* @retval false If the connection is not encrypted or conn_handle is invalid.
*/
bool ble_conn_state_encrypted(uint16_t conn_handle);
/**@brief Function for querying whether a connection encryption is protected from Man in the Middle
* attacks.
*
* @param[in] conn_handle Handle of connection to get the MITM state for.
*
* @retval true If the connection is encrypted with MITM protection.
* @retval false If the connection is not encrypted, or encryption is not MITM protected, or
* conn_handle is invalid.
*/
bool ble_conn_state_mitm_protected(uint16_t conn_handle);
/**@brief Function for querying the total number of connections.
*
* @return The total number of valid connections for which the module has a record.
*/
uint32_t ble_conn_state_n_connections(void);
/**@brief Function for querying the total number of connections in which the role of the local
* device is @ref BLE_GAP_ROLE_CENTRAL.
*
* @return The number of connections in which the role of the local device is
* @ref BLE_GAP_ROLE_CENTRAL.
*/
uint32_t ble_conn_state_n_centrals(void);
/**@brief Function for querying the total number of connections in which the role of the local
* device is @ref BLE_GAP_ROLE_PERIPH.
*
* @return The number of connections in which the role of the local device is
* @ref BLE_GAP_ROLE_PERIPH.
*/
uint32_t ble_conn_state_n_peripherals(void);
/**@brief Function for obtaining a list of all connection handles for which the module has a record.
*
* @details This function takes into account connections whose state is BLE_CONN_STATUS_DISCONNECTED.
*
* @return A list of all valid connection handles for which the module has a record.
*/
sdk_mapped_flags_key_list_t ble_conn_state_conn_handles(void);
/**@brief Function for obtaining a list of connection handles in which the role of the local
* device is @ref BLE_GAP_ROLE_CENTRAL.
*
* @details This function takes into account connections whose state is BLE_CONN_STATUS_DISCONNECTED.
*
* @return A list of all valid connection handles for which the module has a record and in which
* the role of local device is @ref BLE_GAP_ROLE_CENTRAL.
*/
sdk_mapped_flags_key_list_t ble_conn_state_central_handles(void);
/**@brief Function for obtaining the handle for the connection in which the role of the local device
* is @ref BLE_GAP_ROLE_PERIPH.
*
* @details This function takes into account connections whose state is BLE_CONN_STATUS_DISCONNECTED.
*
* @return A list of all valid connection handles for which the module has a record and in which
* the role of local device is @ref BLE_GAP_ROLE_PERIPH.
*/
sdk_mapped_flags_key_list_t ble_conn_state_periph_handles(void);
/**@brief Function for obtaining exclusive access to one of the user flag collections.
*
* @details The acquired collection contains one flag for each connection. These flags can be set
* and read individually for each connection.
*
* The state of user flags will not be modified by the connection state module, except to
* set it to 0 for a connection when that connection is invalidated.
*
* @return The ID of the acquired flag, or BLE_CONN_STATE_USER_FLAG_INVALID if none are available.
*/
ble_conn_state_user_flag_id_t ble_conn_state_user_flag_acquire(void);
/**@brief Function for reading the value of a user flag.
*
* @param[in] conn_handle Handle of connection to get the flag state for.
* @param[in] flag_id Which flag to get the state for.
*
* @return The state of the flag. If conn_handle is invalid, the function returns false.
*/
bool ble_conn_state_user_flag_get(uint16_t conn_handle, ble_conn_state_user_flag_id_t flag_id);
/**@brief Function for setting the value of a user flag.
*
* @param[in] conn_handle Handle of connection to set the flag state for.
* @param[in] flag_id Which flag to set the state for.
* @param[in] value Value to set the flag state to.
*/
void ble_conn_state_user_flag_set(uint16_t conn_handle,
ble_conn_state_user_flag_id_t flag_id,
bool value);
/**@brief Function for getting the state of a user flag for all connection handles.
*
* @details The returned collection can be used with the @ref sdk_mapped_flags API. The returned
* collection is a copy, so modifying it has no effect on the conn_state module.
*
* @param[in] flag_id Which flag to get states for.
*
* @return The collection of flag states. The collection is always all zeros when the flag_id is
* unregistered.
*/
sdk_mapped_flags_t ble_conn_state_user_flag_collection(ble_conn_state_user_flag_id_t flag_id);
/** @} */
/** @} */
#endif /* BLE_CONN_STATE_H__ */

View File

@ -1,104 +0,0 @@
/*
* Copyright (c) 2011 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
*
*/
/* Attention!
* To maintain compliance with Nordic Semiconductor ASAs Bluetooth profile
* qualification listings, this section of source code must not be modified.
*/
/** @file
* @brief Contains definition of ble_date_time structure.
*/
/** @file
*
* @defgroup ble_sdk_srv_date_time BLE Date Time characteristic type
* @{
* @ingroup ble_sdk_lib
* @brief Definition of ble_date_time_t type.
*/
#ifndef BLE_DATE_TIME_H__
#define BLE_DATE_TIME_H__
#include <stdint.h>
/**@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;
static __INLINE uint8_t ble_date_time_encode(const ble_date_time_t * p_date_time,
uint8_t * p_encoded_data)
{
uint8_t len = uint16_encode(p_date_time->year, p_encoded_data);
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;
}
static __INLINE uint8_t ble_date_time_decode(ble_date_time_t * p_date_time,
const uint8_t * p_encoded_data)
{
uint8_t len = sizeof(uint16_t);
p_date_time->year = uint16_decode(p_encoded_data);
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 = p_encoded_data[len++];
return len;
}
#endif // BLE_DATE_TIME_H__
/** @} */

View File

@ -1,77 +0,0 @@
/*
* Copyright (c) 2016 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**@file
*
* @defgroup ble_sdk_lib_gatt_db GATT Database Service Structure
* @{
* @ingroup app_common
*/
#ifndef BLE_GATT_DB_H__
#define BLE_GATT_DB_H__
#include <stdint.h>
#include "nrf_ble.h"
#include "nrf_ble_gattc.h"
#define BLE_GATT_DB_MAX_CHARS 5 /**< The maximum number of characteristics present in a service record. */
/**@brief Structure for holding the characteristic and the handle of its CCCD present on a server.
*/
typedef struct
{
ble_gattc_char_t characteristic; /**< Structure containing information about the characteristic. */
uint16_t cccd_handle; /**< CCCD Handle value for this characteristic. This will be set to BLE_GATT_HANDLE_INVALID if a CCCD is not present at the server. */
} ble_gatt_db_char_t;
/**@brief Structure for holding information about the service and the characteristics present on a
* server.
*/
typedef struct
{
ble_uuid_t srv_uuid; /**< UUID of the service. */
uint8_t char_count; /**< Number of characteristics present in the service. */
ble_gattc_handle_range_t handle_range; /**< Service Handle Range. */
ble_gatt_db_char_t charateristics[BLE_GATT_DB_MAX_CHARS]; /**< Array of information related to the characteristics present in the service. This list can extend further than one. */
} ble_gatt_db_srv_t;
#endif /* BLE_GATT_DB_H__ */
/** @} */

View File

@ -1,67 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
*
*/
/* Attention!
* To maintain compliance with Nordic Semiconductor ASAs Bluetooth profile
* qualification listings, this section of source code must not be modified.
*/
#ifndef BLE_SENSOR_LOCATION_H__
#define BLE_SENSOR_LOCATION_H__
typedef enum {
BLE_SENSOR_LOCATION_OTHER = 0 , /**<-- Other */
BLE_SENSOR_LOCATION_TOP_OF_SHOE = 1 , /**<-- Top of shoe */
BLE_SENSOR_LOCATION_IN_SHOE = 2 , /**<-- In shoe */
BLE_SENSOR_LOCATION_HIP = 3 , /**<-- Hip */
BLE_SENSOR_LOCATION_FRONT_WHEEL = 4 , /**<-- Front Wheel */
BLE_SENSOR_LOCATION_LEFT_CRANK = 5 , /**<-- Left Crank */
BLE_SENSOR_LOCATION_RIGHT_CRANK = 6 , /**<-- Right Crank */
BLE_SENSOR_LOCATION_LEFT_PEDAL = 7 , /**<-- Left Pedal */
BLE_SENSOR_LOCATION_RIGHT_PEDAL = 8 , /**<-- Right Pedal */
BLE_SENSOR_LOCATION_FRONT_HUB = 9 , /**<-- Front Hub */
BLE_SENSOR_LOCATION_REAR_DROPOUT = 10, /**<-- Rear Dropout */
BLE_SENSOR_LOCATION_CHAINSTAY = 11, /**<-- Chainstay */
BLE_SENSOR_LOCATION_REAR_WHEEL = 12, /**<-- Rear Wheel */
BLE_SENSOR_LOCATION_REAR_HUB = 13, /**<-- Rear Hub */
}ble_sensor_location_t;
#define BLE_NB_MAX_SENSOR_LOCATIONS 14
#endif // BLE_SENSOR_LOCATION_H__

View File

@ -1,224 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
*
*/
/* Attention!
* To maintain compliance with Nordic Semiconductor ASA<EFBFBD>s Bluetooth profile
* qualification listings, this section of source code must not be modified.
*/
#include "ble_srv_common.h"
#include <string.h>
#include "nordic_common.h"
#include "app_error.h"
#include "nrf_ble.h"
uint8_t ble_srv_report_ref_encode(uint8_t * p_encoded_buffer,
const ble_srv_report_ref_t * p_report_ref)
{
uint8_t len = 0;
p_encoded_buffer[len++] = p_report_ref->report_id;
p_encoded_buffer[len++] = p_report_ref->report_type;
APP_ERROR_CHECK_BOOL(len == BLE_SRV_ENCODED_REPORT_REF_LEN);
return len;
}
void ble_srv_ascii_to_utf8(ble_srv_utf8_str_t * p_utf8, char * p_ascii)
{
p_utf8->length = (uint16_t)strlen(p_ascii);
p_utf8->p_str = (uint8_t *)p_ascii;
}
/**@brief Function for setting security requirements of a characteristic.
*
* @param[in] level required security level.
* @param[out] p_perm Characteristic security requirements.
*
* @return encoded security level and security mode.
*/
static inline void set_security_req(security_req_t level, ble_gap_conn_sec_mode_t * p_perm)
{
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(p_perm);
switch (level)
{
case SEC_NO_ACCESS:
BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(p_perm);
break;
case SEC_OPEN:
BLE_GAP_CONN_SEC_MODE_SET_OPEN(p_perm);
break;
case SEC_JUST_WORKS:
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(p_perm);
break;
case SEC_MITM:
BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(p_perm);
break;
case SEC_SIGNED:
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(p_perm);
break;
case SEC_SIGNED_MITM:
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(p_perm);
break;
}
return;
}
uint32_t characteristic_add(uint16_t service_handle,
ble_add_char_params_t * p_char_props,
ble_gatts_char_handles_t * p_char_handle)
{
ble_gatts_char_md_t char_md;
ble_gatts_attr_t attr_char_value;
ble_uuid_t char_uuid;
ble_gatts_attr_md_t attr_md;
ble_gatts_attr_md_t user_descr_attr_md;
ble_gatts_attr_md_t cccd_md;
if (p_char_props->uuid_type == 0)
{
char_uuid.type = BLE_UUID_TYPE_BLE;
}
else
{
char_uuid.type = p_char_props->uuid_type;
}
char_uuid.uuid = p_char_props->uuid;
memset(&attr_md, 0, sizeof(ble_gatts_attr_md_t));
set_security_req(p_char_props->read_access, &attr_md.read_perm);
set_security_req(p_char_props->write_access, & attr_md.write_perm);
attr_md.rd_auth = (p_char_props->is_defered_read ? 1 : 0);
attr_md.wr_auth = (p_char_props->is_defered_write ? 1 : 0);
attr_md.vlen = (p_char_props->is_var_len ? 1 : 0);
attr_md.vloc = (p_char_props->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK);
memset(&char_md, 0, sizeof(ble_gatts_char_md_t));
if ((p_char_props->char_props.notify == 1)||(p_char_props->char_props.indicate == 1))
{
memset(&cccd_md, 0, sizeof(cccd_md));
set_security_req(p_char_props->cccd_write_access, &cccd_md.write_perm);
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
cccd_md.vloc = BLE_GATTS_VLOC_STACK;
char_md.p_cccd_md = &cccd_md;
}
char_md.char_props = p_char_props->char_props;
memset(&attr_char_value, 0, sizeof(ble_gatts_attr_t));
attr_char_value.p_uuid = &char_uuid;
attr_char_value.p_attr_md = &attr_md;
attr_char_value.max_len = p_char_props->max_len;
if (p_char_props->p_init_value != NULL)
{
attr_char_value.init_len = p_char_props->init_len;
attr_char_value.p_value = p_char_props->p_init_value;
}
if (p_char_props->p_user_descr != NULL)
{
memset(&user_descr_attr_md, 0, sizeof(ble_gatts_attr_md_t));
char_md.char_user_desc_max_size = p_char_props->p_user_descr->max_size;
char_md.char_user_desc_size = p_char_props->p_user_descr->size;
char_md.p_char_user_desc = p_char_props->p_user_descr->p_char_user_desc;
char_md.p_user_desc_md = &user_descr_attr_md;
set_security_req(p_char_props->p_user_descr->read_access, &user_descr_attr_md.read_perm);
set_security_req(p_char_props->p_user_descr->write_access, &user_descr_attr_md.write_perm);
user_descr_attr_md.rd_auth = (p_char_props->p_user_descr->is_defered_read ? 1 : 0);
user_descr_attr_md.wr_auth = (p_char_props->p_user_descr->is_defered_write ? 1 : 0);
user_descr_attr_md.vlen = (p_char_props->p_user_descr->is_var_len ? 1 : 0);
user_descr_attr_md.vloc = (p_char_props->p_user_descr->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK);
}
if (p_char_props->p_presentation_format != NULL)
{
char_md.p_char_pf = p_char_props->p_presentation_format;
}
return sd_ble_gatts_characteristic_add(service_handle,
&char_md,
&attr_char_value,
p_char_handle);
}
uint32_t descriptor_add(uint16_t char_handle,
ble_add_descr_params_t * p_descr_props,
uint16_t * p_descr_handle)
{
ble_gatts_attr_t descr_params;
ble_uuid_t desc_uuid;
ble_gatts_attr_md_t attr_md;
memset(&descr_params, 0, sizeof(descr_params));
if (p_descr_props->uuid_type == 0)
{
desc_uuid.type = BLE_UUID_TYPE_BLE;
}
else
{
desc_uuid.type = p_descr_props->uuid_type;
}
desc_uuid.uuid = p_descr_props->uuid;
descr_params.p_uuid = &desc_uuid;
set_security_req(p_descr_props->read_access, &attr_md.read_perm);
set_security_req(p_descr_props->write_access,&attr_md.write_perm);
attr_md.rd_auth = (p_descr_props->is_defered_read ? 1 : 0);
attr_md.wr_auth = (p_descr_props->is_defered_write ? 1 : 0);
attr_md.vlen = (p_descr_props->is_var_len ? 1 : 0);
attr_md.vloc = (p_descr_props->is_value_user ? BLE_GATTS_VLOC_USER : BLE_GATTS_VLOC_STACK);
descr_params.p_attr_md = &attr_md;
descr_params.init_len = p_descr_props->init_len;
descr_params.init_offs = p_descr_props->init_offs;
descr_params.max_len = p_descr_props->max_len;
descr_params.p_value = p_descr_props->p_value;
return sd_ble_gatts_descriptor_add(char_handle, &descr_params, p_descr_handle);
}

View File

@ -1,394 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/** @file
*
* @defgroup ble_sdk_srv_common Common service definitions
* @{
* @ingroup ble_sdk_srv
* @brief Constants, type definitions, and functions that are common to all services.
*/
#ifndef BLE_SRV_COMMON_H__
#define BLE_SRV_COMMON_H__
#include <stdint.h>
#include <stdbool.h>
#include "nrf_ble_types.h"
#include "app_util.h"
#include "nrf_ble.h"
#include "nrf_ble_gap.h"
#include "nrf_ble_gatt.h"
/** @defgroup UUID_SERVICES Service UUID definitions
* @{ */
#define BLE_UUID_ALERT_NOTIFICATION_SERVICE 0x1811 /**< Alert Notification service UUID. */
#define BLE_UUID_BATTERY_SERVICE 0x180F /**< Battery service UUID. */
#define BLE_UUID_BLOOD_PRESSURE_SERVICE 0x1810 /**< Blood Pressure service UUID. */
#define BLE_UUID_CURRENT_TIME_SERVICE 0x1805 /**< Current Time service UUID. */
#define BLE_UUID_CYCLING_SPEED_AND_CADENCE 0x1816 /**< Cycling Speed and Cadence service UUID. */
#define BLE_UUID_LOCATION_AND_NAVIGATION_SERVICE 0x1819 /**< Location and Navigation service UUID. */
#define BLE_UUID_DEVICE_INFORMATION_SERVICE 0x180A /**< Device Information service UUID. */
#define BLE_UUID_GLUCOSE_SERVICE 0x1808 /**< Glucose service UUID. */
#define BLE_UUID_HEALTH_THERMOMETER_SERVICE 0x1809 /**< Health Thermometer service UUID. */
#define BLE_UUID_HEART_RATE_SERVICE 0x180D /**< Heart Rate service UUID. */
#define BLE_UUID_HUMAN_INTERFACE_DEVICE_SERVICE 0x1812 /**< Human Interface Device service UUID. */
#define BLE_UUID_IMMEDIATE_ALERT_SERVICE 0x1802 /**< Immediate Alert service UUID. */
#define BLE_UUID_LINK_LOSS_SERVICE 0x1803 /**< Link Loss service UUID. */
#define BLE_UUID_NEXT_DST_CHANGE_SERVICE 0x1807 /**< Next Dst Change service UUID. */
#define BLE_UUID_PHONE_ALERT_STATUS_SERVICE 0x180E /**< Phone Alert Status service UUID. */
#define BLE_UUID_REFERENCE_TIME_UPDATE_SERVICE 0x1806 /**< Reference Time Update service UUID. */
#define BLE_UUID_RUNNING_SPEED_AND_CADENCE 0x1814 /**< Running Speed and Cadence service UUID. */
#define BLE_UUID_SCAN_PARAMETERS_SERVICE 0x1813 /**< Scan Parameters service UUID. */
#define BLE_UUID_TX_POWER_SERVICE 0x1804 /**< TX Power service UUID. */
#define BLE_UUID_IPSP_SERVICE 0x1820 /**< Internet Protocol Support service UUID. */
#define BLE_UUID_BMS_SERVICE 0x181E /**< BOND MANAGEMENT service UUID*/
#define BLE_UUID_CGM_SERVICE 0x181F /**< Contiunous Glucose Monitoring service UUID*/
#define BLE_UUID_PLX_SERVICE 0x1822 /**< Pulse Oximeter Service UUID*/
/** @} */
/** @defgroup UUID_CHARACTERISTICS Characteristic UUID definitions
* @{ */
#define BLE_UUID_REMOVABLE_CHAR 0x2A3A /**< Removable characteristic UUID. */
#define BLE_UUID_SERVICE_REQUIRED_CHAR 0x2A3B /**< Service Required characteristic UUID. */
#define BLE_UUID_ALERT_CATEGORY_ID_CHAR 0x2A43 /**< Alert Category Id characteristic UUID. */
#define BLE_UUID_ALERT_CATEGORY_ID_BIT_MASK_CHAR 0x2A42 /**< Alert Category Id Bit Mask characteristic UUID. */
#define BLE_UUID_ALERT_LEVEL_CHAR 0x2A06 /**< Alert Level characteristic UUID. */
#define BLE_UUID_ALERT_NOTIFICATION_CONTROL_POINT_CHAR 0x2A44 /**< Alert Notification Control Point characteristic UUID. */
#define BLE_UUID_ALERT_STATUS_CHAR 0x2A3F /**< Alert Status characteristic UUID. */
#define BLE_UUID_BATTERY_LEVEL_CHAR 0x2A19 /**< Battery Level characteristic UUID. */
#define BLE_UUID_BLOOD_PRESSURE_FEATURE_CHAR 0x2A49 /**< Blood Pressure Feature characteristic UUID. */
#define BLE_UUID_BLOOD_PRESSURE_MEASUREMENT_CHAR 0x2A35 /**< Blood Pressure Measurement characteristic UUID. */
#define BLE_UUID_BODY_SENSOR_LOCATION_CHAR 0x2A38 /**< Body Sensor Location characteristic UUID. */
#define BLE_UUID_BOOT_KEYBOARD_INPUT_REPORT_CHAR 0x2A22 /**< Boot Keyboard Input Report characteristic UUID. */
#define BLE_UUID_BOOT_KEYBOARD_OUTPUT_REPORT_CHAR 0x2A32 /**< Boot Keyboard Output Report characteristic UUID. */
#define BLE_UUID_BOOT_MOUSE_INPUT_REPORT_CHAR 0x2A33 /**< Boot Mouse Input Report characteristic UUID. */
#define BLE_UUID_CURRENT_TIME_CHAR 0x2A2B /**< Current Time characteristic UUID. */
#define BLE_UUID_DATE_TIME_CHAR 0x2A08 /**< Date Time characteristic UUID. */
#define BLE_UUID_DAY_DATE_TIME_CHAR 0x2A0A /**< Day Date Time characteristic UUID. */
#define BLE_UUID_DAY_OF_WEEK_CHAR 0x2A09 /**< Day Of Week characteristic UUID. */
#define BLE_UUID_DST_OFFSET_CHAR 0x2A0D /**< Dst Offset characteristic UUID. */
#define BLE_UUID_EXACT_TIME_256_CHAR 0x2A0C /**< Exact Time 256 characteristic UUID. */
#define BLE_UUID_FIRMWARE_REVISION_STRING_CHAR 0x2A26 /**< Firmware Revision String characteristic UUID. */
#define BLE_UUID_GLUCOSE_FEATURE_CHAR 0x2A51 /**< Glucose Feature characteristic UUID. */
#define BLE_UUID_GLUCOSE_MEASUREMENT_CHAR 0x2A18 /**< Glucose Measurement characteristic UUID. */
#define BLE_UUID_GLUCOSE_MEASUREMENT_CONTEXT_CHAR 0x2A34 /**< Glucose Measurement Context characteristic UUID. */
#define BLE_UUID_HARDWARE_REVISION_STRING_CHAR 0x2A27 /**< Hardware Revision String characteristic UUID. */
#define BLE_UUID_HEART_RATE_CONTROL_POINT_CHAR 0x2A39 /**< Heart Rate Control Point characteristic UUID. */
#define BLE_UUID_HEART_RATE_MEASUREMENT_CHAR 0x2A37 /**< Heart Rate Measurement characteristic UUID. */
#define BLE_UUID_HID_CONTROL_POINT_CHAR 0x2A4C /**< Hid Control Point characteristic UUID. */
#define BLE_UUID_HID_INFORMATION_CHAR 0x2A4A /**< Hid Information characteristic UUID. */
#define BLE_UUID_IEEE_REGULATORY_CERTIFICATION_DATA_LIST_CHAR 0x2A2A /**< IEEE Regulatory Certification Data List characteristic UUID. */
#define BLE_UUID_INTERMEDIATE_CUFF_PRESSURE_CHAR 0x2A36 /**< Intermediate Cuff Pressure characteristic UUID. */
#define BLE_UUID_INTERMEDIATE_TEMPERATURE_CHAR 0x2A1E /**< Intermediate Temperature characteristic UUID. */
#define BLE_UUID_LOCAL_TIME_INFORMATION_CHAR 0x2A0F /**< Local Time Information characteristic UUID. */
#define BLE_UUID_MANUFACTURER_NAME_STRING_CHAR 0x2A29 /**< Manufacturer Name String characteristic UUID. */
#define BLE_UUID_MEASUREMENT_INTERVAL_CHAR 0x2A21 /**< Measurement Interval characteristic UUID. */
#define BLE_UUID_MODEL_NUMBER_STRING_CHAR 0x2A24 /**< Model Number String characteristic UUID. */
#define BLE_UUID_UNREAD_ALERT_CHAR 0x2A45 /**< Unread Alert characteristic UUID. */
#define BLE_UUID_NEW_ALERT_CHAR 0x2A46 /**< New Alert characteristic UUID. */
#define BLE_UUID_PNP_ID_CHAR 0x2A50 /**< PNP Id characteristic UUID. */
#define BLE_UUID_PROTOCOL_MODE_CHAR 0x2A4E /**< Protocol Mode characteristic UUID. */
#define BLE_UUID_RECORD_ACCESS_CONTROL_POINT_CHAR 0x2A52 /**< Record Access Control Point characteristic UUID. */
#define BLE_UUID_REFERENCE_TIME_INFORMATION_CHAR 0x2A14 /**< Reference Time Information characteristic UUID. */
#define BLE_UUID_REPORT_CHAR 0x2A4D /**< Report characteristic UUID. */
#define BLE_UUID_REPORT_MAP_CHAR 0x2A4B /**< Report Map characteristic UUID. */
#define BLE_UUID_RINGER_CONTROL_POINT_CHAR 0x2A40 /**< Ringer Control Point characteristic UUID. */
#define BLE_UUID_RINGER_SETTING_CHAR 0x2A41 /**< Ringer Setting characteristic UUID. */
#define BLE_UUID_SCAN_INTERVAL_WINDOW_CHAR 0x2A4F /**< Scan Interval Window characteristic UUID. */
#define BLE_UUID_SCAN_REFRESH_CHAR 0x2A31 /**< Scan Refresh characteristic UUID. */
#define BLE_UUID_SERIAL_NUMBER_STRING_CHAR 0x2A25 /**< Serial Number String characteristic UUID. */
#define BLE_UUID_SOFTWARE_REVISION_STRING_CHAR 0x2A28 /**< Software Revision String characteristic UUID. */
#define BLE_UUID_SUPPORTED_NEW_ALERT_CATEGORY_CHAR 0x2A47 /**< Supported New Alert Category characteristic UUID. */
#define BLE_UUID_SUPPORTED_UNREAD_ALERT_CATEGORY_CHAR 0x2A48 /**< Supported Unread Alert Category characteristic UUID. */
#define BLE_UUID_SYSTEM_ID_CHAR 0x2A23 /**< System Id characteristic UUID. */
#define BLE_UUID_TEMPERATURE_MEASUREMENT_CHAR 0x2A1C /**< Temperature Measurement characteristic UUID. */
#define BLE_UUID_TEMPERATURE_TYPE_CHAR 0x2A1D /**< Temperature Type characteristic UUID. */
#define BLE_UUID_TIME_ACCURACY_CHAR 0x2A12 /**< Time Accuracy characteristic UUID. */
#define BLE_UUID_TIME_SOURCE_CHAR 0x2A13 /**< Time Source characteristic UUID. */
#define BLE_UUID_TIME_UPDATE_CONTROL_POINT_CHAR 0x2A16 /**< Time Update Control Point characteristic UUID. */
#define BLE_UUID_TIME_UPDATE_STATE_CHAR 0x2A17 /**< Time Update State characteristic UUID. */
#define BLE_UUID_TIME_WITH_DST_CHAR 0x2A11 /**< Time With Dst characteristic UUID. */
#define BLE_UUID_TIME_ZONE_CHAR 0x2A0E /**< Time Zone characteristic UUID. */
#define BLE_UUID_TX_POWER_LEVEL_CHAR 0x2A07 /**< TX Power Level characteristic UUID. */
#define BLE_UUID_CSC_FEATURE_CHAR 0x2A5C /**< Cycling Speed and Cadence Feature characteristic UUID. */
#define BLE_UUID_CSC_MEASUREMENT_CHAR 0x2A5B /**< Cycling Speed and Cadence Measurement characteristic UUID. */
#define BLE_UUID_RSC_FEATURE_CHAR 0x2A54 /**< Running Speed and Cadence Feature characteristic UUID. */
#define BLE_UUID_SC_CTRLPT_CHAR 0x2A55 /**< Speed and Cadence Control Point UUID. */
#define BLE_UUID_RSC_MEASUREMENT_CHAR 0x2A53 /**< Running Speed and Cadence Measurement characteristic UUID. */
#define BLE_UUID_SENSOR_LOCATION_CHAR 0x2A5D /**< Sensor Location characteristic UUID. */
#define BLE_UUID_EXTERNAL_REPORT_REF_DESCR 0x2907 /**< External Report Reference descriptor UUID. */
#define BLE_UUID_REPORT_REF_DESCR 0x2908 /**< Report Reference descriptor UUID. */
#define BLE_UUID_LN_FEATURE_CHAR 0x2A6A /**< Location Navigation Service, Feature characteristic UUID. */
#define BLE_UUID_LN_POSITION_QUALITY_CHAR 0x2A69 /**< Location Navigation Service, Position quality UUID. */
#define BLE_UUID_LN_LOCATION_AND_SPEED_CHAR 0x2A67 /**< Location Navigation Service, Location and Speed characteristic UUID. */
#define BLE_UUID_LN_NAVIGATION_CHAR 0x2A68 /**< Location Navigation Service, Navigation characteristic UUID. */
#define BLE_UUID_LN_CONTROL_POINT_CHAR 0x2A6B /**< Location Navigation Service, Control point characteristic UUID. */
#define BLE_UUID_BMS_CTRLPT 0x2AA4 /**< BMS Control Point characteristic UUID. */
#define BLE_UUID_BMS_FEATURE 0x2AA5 /**< BMS Feature characteristic UUID. */
#define BLE_UUID_CGM_MEASUREMENT 0x2AA7 /**< CGM Service, Measurement characteristic UUID*/
#define BLE_UUID_CGM_FEATURE 0x2AA8 /**< CGM Service, Feature characteristic UUID*/
#define BLE_UUID_CGM_STATUS 0x2AA9 /**< CGM Service, Status characteristic UUID*/
#define BLE_UUID_CGM_SESSION_START_TIME 0x2AAA /**< CGM Service, session start time characteristic UUID*/
#define BLE_UUID_CGM_SESSION_RUN_TIME 0x2AAB /**< CGM Service, session run time characteristic UUID*/
#define BLE_UUID_CGM_SPECIFIC_OPS_CTRLPT 0x2AAC /**< CGM Service, specific ops ctrlpt characteristic UUID*/
#define BLE_UUID_PLX_SPOT_CHECK_MEAS 0x2A5E /**< PLX Service, spot check measurement characteristic UUID*/
#define BLE_UUID_PLX_CONTINUOUS_MEAS 0x2A5F /**< PLX Service, continuous measurement characteristic UUID*/
#define BLE_UUID_PLX_FEATURES 0x2A60 /**< PLX Service, feature characteristic UUID*/
/** @} */
/** @defgroup ALERT_LEVEL_VALUES Definitions for the Alert Level characteristic values
* @{ */
#define BLE_CHAR_ALERT_LEVEL_NO_ALERT 0x00 /**< No Alert. */
#define BLE_CHAR_ALERT_LEVEL_MILD_ALERT 0x01 /**< Mild Alert. */
#define BLE_CHAR_ALERT_LEVEL_HIGH_ALERT 0x02 /**< High Alert. */
/** @} */
#define BLE_SRV_ENCODED_REPORT_REF_LEN 2 /**< The length of an encoded Report Reference Descriptor. */
#define BLE_CCCD_VALUE_LEN 2 /**< The length of a CCCD value. */
/**@brief Type definition for error handler function that will be called in case of an error in
* a service or a service library module. */
typedef void (*ble_srv_error_handler_t) (uint32_t nrf_error);
/**@brief Value of a Report Reference descriptor.
*
* @details This is mapping information that maps the parent characteristic to the Report ID(s) and
* Report Type(s) defined within a Report Map characteristic.
*/
typedef struct
{
uint8_t report_id; /**< Non-zero value if there is more than one instance of the same Report Type */
uint8_t report_type; /**< Type of Report characteristic (see @ref BLE_HIDS_REPORT_TYPE) */
} ble_srv_report_ref_t;
/**@brief UTF-8 string data type.
*
* @note The type can only hold a pointer to the string data (i.e. not the actual data).
*/
typedef struct
{
uint16_t length; /**< String length. */
uint8_t * p_str; /**< String data. */
} ble_srv_utf8_str_t;
/**@brief Security settings structure.
* @details This structure contains the security options needed during initialization of the
* service.
*/
typedef struct
{
ble_gap_conn_sec_mode_t read_perm; /**< Read permissions. */
ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */
} ble_srv_security_mode_t;
/**@brief Security settings structure.
* @details This structure contains the security options needed during initialization of the
* service. It can be used when the characteristics contains a CCCD.
*/
typedef struct
{
ble_gap_conn_sec_mode_t cccd_write_perm; /**< Write permissions for Client Characteristic Configuration Descriptor. */
ble_gap_conn_sec_mode_t read_perm; /**< Read permissions. */
ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */
} ble_srv_cccd_security_mode_t;
/**@brief Function for decoding a CCCD value, and then testing if notification is
* enabled.
*
* @param[in] p_encoded_data Buffer where the encoded CCCD is stored.
*
* @retval TRUE If notification is enabled.
* @retval FALSE Otherwise.
*/
static __INLINE bool ble_srv_is_notification_enabled(uint8_t const * p_encoded_data)
{
uint16_t cccd_value = uint16_decode(p_encoded_data);
return ((cccd_value & BLE_GATT_HVX_NOTIFICATION) != 0);
}
/**@brief Function for decoding a CCCD value, and then testing if indication is
* enabled.
*
* @param[in] p_encoded_data Buffer where the encoded CCCD is stored.
*
* @retval TRUE If indication is enabled.
* @retval FALSE Otherwise.
*/
static __INLINE bool ble_srv_is_indication_enabled(uint8_t const * p_encoded_data)
{
uint16_t cccd_value = uint16_decode(p_encoded_data);
return ((cccd_value & BLE_GATT_HVX_INDICATION) != 0);
}
/**@brief Function for encoding a Report Reference Descriptor.
*
* @param[in] p_encoded_buffer The buffer of the encoded data.
* @param[in] p_report_ref Report Reference value to be encoded.
*
* @return Length of the encoded data.
*/
uint8_t ble_srv_report_ref_encode(uint8_t * p_encoded_buffer,
const ble_srv_report_ref_t * p_report_ref);
/**@brief Function for making a UTF-8 structure refer to an ASCII string.
*
* @param[out] p_utf8 UTF-8 structure to be set.
* @param[in] p_ascii ASCII string to be referred to.
*/
void ble_srv_ascii_to_utf8(ble_srv_utf8_str_t * p_utf8, char * p_ascii);
/**@brief Security Access enumeration.
* @details This enumeration gives the possible requirements for accessing a characteristic value.
*/
typedef enum
{
SEC_NO_ACCESS = 0, /**< Not possible to access. */
SEC_OPEN = 1, /**< Access open. */
SEC_JUST_WORKS = 2, /**< Access possible with 'Just Works' security at least. */
SEC_MITM = 3, /**< Access possible with 'MITM' security at least. */
SEC_SIGNED = 4, /**< Access possible with 'signed' security at least. */
SEC_SIGNED_MITM = 5 /**< Access possible with 'signed and MITM' security at least. */
}security_req_t;
/**@brief Characteristic User Descriptor parameters.
* @details This structure contains the parameters for User Descriptor.
*/
typedef struct
{
uint16_t max_size; /**< Maximum size of the user descriptor*/
uint16_t size; /**< Size of the user descriptor*/
uint8_t *p_char_user_desc; /**< User descriptor content, pointer to a UTF-8 encoded string (non-NULL terminated)*/
bool is_var_len; /**< Indicates if the user descriptor has variable length.*/
ble_gatt_char_props_t char_props; /**< user descriptor properties.*/
bool is_defered_read; /**< Indicate if deferred read operations are supported.*/
bool is_defered_write; /**< Indicate if deferred write operations are supported.*/
security_req_t read_access; /**< Security requirement for reading the user descriptor.*/
security_req_t write_access; /**< Security requirement for writing the user descriptor.*/
bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/
}ble_add_char_user_desc_t;
/**@brief Add characteristic parameters structure.
* @details This structure contains the parameters needed to use the @ref characteristic_add function.
*/
typedef struct
{
uint16_t uuid; /**< Characteristic UUID (16 bits UUIDs).*/
uint8_t uuid_type; /**< Base UUID. If 0, the Bluetooth SIG UUID will be used. Otherwise, this should be a value returned by @ref sd_ble_uuid_vs_add when adding the base UUID.*/
uint16_t max_len; /**< Maximum length of the characteristic value.*/
uint16_t init_len; /**< Initial length of the characteristic value.*/
uint8_t * p_init_value; /**< Initial encoded value of the characteristic.*/
bool is_var_len; /**< Indicates if the characteristic value has variable length.*/
ble_gatt_char_props_t char_props; /**< Characteristic properties.*/
bool is_defered_read; /**< Indicate if deferred read operations are supported.*/
bool is_defered_write; /**< Indicate if deferred write operations are supported.*/
security_req_t read_access; /**< Security requirement for reading the characteristic value.*/
security_req_t write_access; /**< Security requirement for writing the characteristic value.*/
security_req_t cccd_write_access; /**< Security requirement for writing the characteristic's CCCD.*/
bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/
ble_add_char_user_desc_t *p_user_descr; /**< Pointer to user descriptor if needed*/
ble_gatts_char_pf_t *p_presentation_format; /**< Pointer to characteristic format if needed*/
} ble_add_char_params_t;
/**@brief Add descriptor parameters structure.
* @details This structure contains the parameters needed to use the @ref descriptor_add function.
*/
typedef struct
{
uint16_t uuid; /**< descriptor UUID (16 bits UUIDs).*/
uint8_t uuid_type; /**< Base UUID. If 0, the Bluetooth SIG UUID will be used. Otherwise, this should be a value returned by @ref sd_ble_uuid_vs_add when adding the base UUID.*/
bool is_defered_read; /**< Indicate if deferred read operations are supported.*/
bool is_defered_write; /**< Indicate if deferred write operations are supported.*/
bool is_var_len; /**< Indicates if the descriptor value has variable length.*/
security_req_t read_access; /**< Security requirement for reading the descriptor value.*/
security_req_t write_access; /**< Security requirement for writing the descriptor value.*/
bool is_value_user; /**< Indicate if the content of the characteristic is to be stored in the application (user) or in the stack.*/
uint16_t init_len; /**< Initial descriptor value length in bytes. */
uint16_t init_offs; /**< Initial descriptor 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 descriptor value length in bytes, see @ref BLE_GATTS_ATTR_LENS_MAX for maximum values. */
uint8_t* p_value; /**< Pointer to the value of the descriptor*/
} ble_add_descr_params_t;
/**@brief Function for adding a characteristic to a given service.
*
* If no pointer is given for the initial value,
* the initial length parameter will be ignored and the initial length will be 0.
*
* @param[in] service_handle Handle of the service to which the characteristic is to be added.
* @param[in] p_char_props Information needed to add the characteristic.
* @param[out] p_char_handle Handle of the added characteristic.
*
* @retval NRF_SUCCESS If the characteristic was added successfully. Otherwise, an error code is returned.
*/
uint32_t characteristic_add(uint16_t service_handle,
ble_add_char_params_t * p_char_props,
ble_gatts_char_handles_t * p_char_handle);
/**@brief Function for adding a characteristic's descriptor to a given characteristic.
*
* @param[in] char_handle Handle of the characteristic to which the descriptor is to be added, if @ref BLE_GATT_HANDLE_INVALID is used, it will be placed sequentially.
* @param[in] p_descr_props Information needed to add the descriptor.
* @param[out] p_descr_handle Handle of the added descriptor.
*
* @retval NRF_SUCCESS If the characteristic was added successfully. Otherwise, an error code is returned.
*/
uint32_t descriptor_add(uint16_t char_handle,
ble_add_descr_params_t * p_descr_props,
uint16_t * p_descr_handle);
#endif // BLE_SRV_COMMON_H__
/** @} */

View File

@ -1,126 +0,0 @@
/*
* Copyright (c) 2013 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 device_manager_cnfg.h
*
* @cond
* @defgroup device_manager_cnfg Device Manager Configuration
* @ingroup device_manager
* @{
*
* @brief Defines application specific configuration for Device Manager.
*
* @details All configurations that are specific to application have been defined
* here. Application should configuration that best suits its requirements.
*/
#ifndef DEVICE_MANAGER_CNFG_H__
#define DEVICE_MANAGER_CNFG_H__
/**
* @defgroup device_manager_inst Device Manager Instances
* @{
*/
/**
* @brief Maximum applications that Device Manager can support.
*
* @details Maximum application that the Device Manager can support.
* Currently only one application can be supported.
* Minimum value : 1
* Maximum value : 1
* Dependencies : None.
*/
#define DEVICE_MANAGER_MAX_APPLICATIONS 1
/**
* @brief Maximum connections that Device Manager should simultaneously manage.
*
* @details Maximum connections that Device Manager should simultaneously manage.
* Minimum value : 1
* Maximum value : Maximum links supported by SoftDevice.
* Dependencies : None.
*/
#define DEVICE_MANAGER_MAX_CONNECTIONS 1
/**
* @brief Maximum bonds that Device Manager should manage.
*
* @details Maximum bonds that Device Manager should manage.
* Minimum value : 1
* Maximum value : 254.
* Dependencies : None.
* @note In case of GAP Peripheral role, the Device Manager will accept bonding procedure
* requests from peers even if this limit is reached, but bonding information will not
* be stored. In such cases, application will be notified with DM_DEVICE_CONTEXT_FULL
* as event result at the completion of the security procedure.
*/
#define DEVICE_MANAGER_MAX_BONDS 7
/**
* @brief Maximum Characteristic Client Descriptors used for GATT Server.
*
* @details Maximum Characteristic Client Descriptors used for GATT Server.
* Minimum value : 1
* Maximum value : 254.
* Dependencies : None.
*/
#define DM_GATT_CCCD_COUNT 2
/**
* @brief Size of application context.
*
* @details Size of application context that Device Manager should manage for each bonded device.
* Size had to be a multiple of word size.
* Minimum value : 4.
* Maximum value : 256.
* Dependencies : Needed only if Application Context saving is used by the application.
* @note If set to zero, its an indication that application context is not required to be managed
* by the module.
*/
#define DEVICE_MANAGER_APP_CONTEXT_SIZE 0
/* @} */
/* @} */
/** @endcond */
#endif // DEVICE_MANAGER_CNFG_H__

View File

@ -1,915 +0,0 @@
/*
* Copyright (c) 2013 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 device_manager.h
*
* @defgroup device_manager Device Manager
* @ingroup ble_sdk_lib
* @{
* @brief Device Manager Application Interface Abstraction.
*
* @details The Device Manager module manages Active and Bonded Peers. Management of peer includes
* book keeping of contextual information like the Security Keys, GATT
* configuration and any application specific information.
*
* Active Peers are devices which are connected, and may or may not be bonded.
* Bonded Peers are devices which are bonded, and may or may not be Active (Connected).
* Active Bonded Peer refers to a device which is connected and bonded.
*
* Paired Devices refers to peer devices that are connected and have necessary context
* establishment/exchange for the current connection session. On disconnect,
* all contextual information is flushed. For example, SMP Information Exchanged during
* pairing and GATT Configuration is not retained on disconnection.
*
* Note that this module allows management of contextual information but
* does not provide an interface for connection management. Therefore, entering connectible
* mode, connection establishment, or disconnection of a link with peer is not in scope
* of this module.
*
* For bonded peers, the contextual information is required to be retained on disconnection
* and power cycling. Persistent storage of contextual information is handled by the
* module. This module categorizes the contextual information into 3 categories:
* - <b>Bonding Information</b>
* Bond information is the information exchanged between local and peer device to
* establish a bond. It also includes peer identification information,
* like the peer address or the IRK or both. From here on this category of information
* is referred to as Device Context.
* - <b>Service/Protocol Information</b>
* Service/Protocol information is the information retained for the peer to save on one-time
* procedures like the GATT Service Discovery procedures and Service Configurations.
* It allows devices to resume data exchange on subsequent reconnection without having
* to perform initial set-up procedures each time. From here on this category is
* referred to as Service Context.
* - <b>Application Information</b>
* Application information is the context that the application would like to associate with
* each of the bonded device. For example, if the application chooses to rank its peers
* in order to manage them better, the rank information could be treated as
* Application Information. This storage space is provided to save the application from
* maintaining a mapping table with each Device Instance and Application Information.
* However, if the application have no use for this, it is possible to not
* use or employ this at compile time. From here on this category of information is
* referred to as Application Context.
*/
#ifndef DEVICE_MANAGER_H__
#define DEVICE_MANAGER_H__
#include <stdint.h>
#include <stdbool.h>
#include "sdk_common.h"
#include "nrf_ble.h"
#include "nrf_ble_gap.h"
#include "device_manager_cnfg.h"
/**
* @defgroup dm_service_cntext_types Service/Protocol Types
*
* @brief Describes the possible types of Service/Protocol Contexts for a bonded/peer device.
*
* @details Possible Service/Protocol context per peer device. The Device Manager provides the
* functionality of persistently storing the Service/Protocol context and can automatically
* load them when needed.
* For example system attributes for a GATT Server. Based on the nature of the application,
* not all service types may be needed. The application can specify
* only the service/protocol context it wants to use at the time of registration.
* @{
*/
#define DM_PROTOCOL_CNTXT_NONE 0x00 /**< No Service Context, this implies the application does not want to associate any service/protocol context with the peer device */
#define DM_PROTOCOL_CNTXT_GATT_SRVR_ID 0x01 /**< GATT Server Service Context, this implies the application does associate GATT Server with the peer device and this information will be loaded when needed for a bonded device */
#define DM_PROTOCOL_CNTXT_GATT_CLI_ID 0x02 /**< GATT Client Service Context, this implies the application does associate GATT Client with the peer device and this information will be loaded when needed for a bonded device */
#define DM_PROTOCOL_CNTXT_ALL \
(DM_PROTOCOL_CNTXT_GATT_SRVR_ID | DM_PROTOCOL_CNTXT_GATT_CLI_ID) /**< All Service/Protocol Context, this implies that the application wants to associate all Service/Protocol Information with the bonded device. This is configurable based on system requirements. If the application has only one type of service, this define could be altered to reflect the same. */
/** @} */
/**
* @defgroup dm_events Device Manager Events
*
* @brief This section describes the device manager events that are notified to the application.
*
* @details The Device Manager notifies the application of various asynchronous events using the
* asynchronous event notification callback. All events has been categorized into:
* a. General.
* b. Link Status.
* c. Context Management.
*
* In the callback, these events are notified along with handle that uniquely identifies:
* application instance, active instance (if applicable), device instance
* bonding instance, (if applicable) and service instance.
* Not all events are pertaining to an active connection, for example a context deletion event could occur even if the peer
* is not connected. Also, general category of events may not be pertaining to any specific peer.
* See also \ref dm_event_cb_t and \ref dm_register.
* @{
*/
/**
* @defgroup general_events General Events
*
* @brief General or miscellaneous events.
*
* @details This category of events are general events not pertaining to a peer or context.
*
* @{
*/
#define DM_EVT_RFU 0x00 /**< Reserved for future use, is never notified. */
#define DM_EVT_ERROR 0x01 /**< Device Manager Event Error. */
/** @} */
/**
* @defgroup link_status_events Link Status Events
*
* @brief Link Status Events.
*
* @details This category of events notify the application of the link status. Event result associated
* with the event is provided along with the event in the callback to provide more details of
* whether a procedure succeeded or failed and assist the application in decision making of
* how to proceed. For example if a DM_DEVICE_CONNECT_IND is indicated with NRF_SUCCESS
* result, the application may want to proceed with discovering and association with
* service of the peer. However, if indicated with a failure result, the application may
* want to take an alternate action such as reattempting to connect or go into a
* sleep mode.
*
* @{
*/
#define DM_EVT_CONNECTION 0x11 /**< Indicates that link with the peer is established. */
#define DM_EVT_DISCONNECTION 0x12 /**< Indicates that link with peer is torn down. */
#define DM_EVT_SECURITY_SETUP 0x13 /**< Security procedure for link started indication */
#define DM_EVT_SECURITY_SETUP_COMPLETE 0x14 /**< Security procedure for link completion indication. */
#define DM_EVT_LINK_SECURED 0x15 /**< Indicates that link with the peer is secured. For bonded devices, subsequent reconnections with bonded peer will result only in this event when the link is secured and setup procedures will not occur unless the bonding information is either lost or deleted on either or both sides. */
#define DM_EVT_SECURITY_SETUP_REFRESH 0x16 /**< Indicates that the security on the link was re-established. */
/** @} */
/**
* @defgroup context_mgmt_events Context Management Events
*
* @brief Context Management Events.
*
* @details These events notify the application of the status of context loading and storing.
*
* @{
*/
#define DM_EVT_DEVICE_CONTEXT_LOADED 0x21 /**< Indicates that device context for a peer is loaded. */
#define DM_EVT_DEVICE_CONTEXT_STORED 0x22 /**< Indicates that device context is stored persistently. */
#define DM_EVT_DEVICE_CONTEXT_DELETED 0x23 /**< Indicates that device context is deleted. */
#define DM_EVT_SERVICE_CONTEXT_LOADED 0x31 /**< Indicates that service context for a peer is loaded. */
#define DM_EVT_SERVICE_CONTEXT_STORED 0x32 /**< Indicates that service context is stored persistently. */
#define DM_EVT_SERVICE_CONTEXT_DELETED 0x33 /**< Indicates that service context is deleted. */
#define DM_EVT_APPL_CONTEXT_LOADED 0x41 /**< Indicates that application context for a peer is loaded. */
#define DM_EVT_APPL_CONTEXT_STORED 0x42 /**< Indicates that application context is stored persistently. */
#define DM_EVT_APPL_CONTEXT_DELETED 0x43 /**< Indicates that application context is deleted. */
/** @} */
/** @} */
#define DM_INVALID_ID 0xFF /**< Invalid instance idenitifer. */
/**
* @defgroup dm_data_structure Device Manager Data Types
*
* @brief This section describes all the data types exposed by the module to the application.
* @{
*/
/**
* @brief Application Instance.
*
* @details Application instance uniquely identifies an application. The identifier is allocated by
* the device manager when application registers with the module. The application is
* expected to identify itself with this instance identifier when initiating subsequent
* requests. Application should use the utility API \ref dm_application_instance_set in
* order to set its application instance in dm_handle_t needed for all subsequent APIs.
* See also \ref dm_register.
*/
typedef uint8_t dm_application_instance_t;
/**
* @brief Connection Instance.
*
* @details Identifies connection instance for an active device. This instance is allocated by the
* device manager when a connection is established and is notified with DM_EVT_CONNECTION
* with the event result NRF_SUCCESS.
*/
typedef uint8_t dm_connection_instance_t;
/**
* @brief Device Instance.
*
* @details Uniquely identifies a bonded peer device. The peer device may or may not be connected.
* In case of the central: The bonded device instance to identify the peer is allocated when bonding procedure is initiated by the central using dm_security_setup_req.
* In case of the peripheral: When the bonding procedure is successful, the DM_EVT_SECURITY_SETUP_COMPLETE event with success event result, is received.
* In case the module cannot add more bonded devices, no instance is allocated, this is indicated by an appropriate error code for the API/event as the case may be. Application can choose to disconnect the link.
*/
typedef uint8_t dm_device_instance_t;
/**
* @brief Service Instance.
*
* @details Uniquely identifies a peer device. The peer device may or may not be connected. This
* instance is allocated by the device manager when a device is bonded and is notified
* when security procedures have been initiated.
* Security Procedures initiation is notified with DM_SECURITY_SETUP_IND with
* success event result. In case the event result indicates that the module cannot add more
* bonded devices, no instance is allocated. Application can chose to disconnect the link.
*/
typedef uint8_t dm_service_instance_t;
/**
* @brief Service/Protocol Type Identifier.
*
* @details Uniquely identifies a service or a protocol type. Service/Protocol Type identification
* is needed as each service/protocol can have its own contextual data.
* This allows the peer to access more than one service at a time. \ref dm_service_cntext_types describes the
* list of services/protocols supported.
*/
typedef uint8_t service_type_t;
/**@brief Device Manager Master identification and encryption information. */
typedef struct dm_enc_key
{
ble_gap_enc_info_t enc_info; /**< GAP encryption information. */
ble_gap_master_id_t master_id; /**< Master identification. */
} dm_enc_key_t;
/** @brief Device Manager identity and address information. */
typedef struct dm_id_key
{
ble_gap_irk_t id_info; /**< Identity information. */
ble_gap_addr_t id_addr_info; /**< Identity address information. */
} dm_id_key_t;
/** @brief Device Manager signing information. */
typedef struct dm_sign_key
{
ble_gap_sign_info_t sign_key; /**< GAP signing information. */
} dm_sign_key_t;
/** @brief Security keys. */
typedef struct dm_sec_keyset
{
union
{
dm_enc_key_t * p_enc_key; /**< Pointer to Device Manager encryption information structure. */
} enc_key;
dm_id_key_t * p_id_key; /**< Identity key, or NULL. */
dm_sign_key_t * p_sign_key; /**< Signing key, or NULL. */
} dm_sec_keys_t;
/** @brief Device Manager security key set. */
typedef struct
{
dm_sec_keys_t keys_periph; /**< Keys distributed by the device in the Peripheral role. */
dm_sec_keys_t keys_central; /**< Keys distributed by the device in the Central role. */
} dm_sec_keyset_t;
/**
* @brief Device Handle used for unique identification of each peer.
*
* @details This data type is used to uniquely identify each peer device. A peer device could be
* active and/or bonded. Therefore an instance for active and bonded is provided.
* However, the application is expected to treat this is an opaque structure and use this for
* all API interactions once stored on appropriate events.
* See \ref dm_events.
*/
typedef struct device_handle
{
dm_application_instance_t appl_id; /**< Identifies the application instances for the device that is being managed. */
dm_connection_instance_t connection_id; /**< Identifies the active connection instance. */
dm_device_instance_t device_id; /**< Identifies peer instance in the data base. */
dm_service_instance_t service_id; /**< Service instance identifier. */
} dm_handle_t;
/**
* @brief Definition of Data Context.
*
* @details Defines contextual data format, it consists of context data length and pointer to data.
*/
typedef struct
{
uint32_t flags; /**< Additional flags identifying data. */
uint32_t len; /**< Length of data. */
uint8_t * p_data; /**< Pointer to contextual data, a copy is made of the data. */
} dm_context_t;
/**
* @brief Device Context.
*
* @details Defines "device context" type for a device managed by device manager.
*/
typedef dm_context_t dm_device_context_t;
/**
* @brief Service Context.
*
* @details Service context data for a service identified by the 'service_type' field.
*/
typedef struct
{
service_type_t service_type; /**< Identifies the service/protocol to which the context data is related. */
dm_context_t context_data; /**< Contains length and pointer to context data */
} dm_service_context_t;
/**
* @brief Application context.
*
* @details The application context can be used by the application to map any application level
* information that is to be mapped with a particular peer.
* For bonded peers, this information will be stored by the bond manager persistently.
* Note that the device manager treats this information as an
* opaque block of bytes.
* Necessary APIs to get and set this context for a peer have been provided.
*/
typedef dm_context_t dm_application_context_t;
/**
* @brief Event parameters.
*
* @details Defines event parameters for each of the events notified by the module.
*/
typedef union
{
ble_gap_evt_t * p_gap_param; /**< All events that are triggered in device manager as a result of GAP events, like connection, disconnection and security procedures are accompanied with GAP parameters. */
dm_application_context_t * p_app_context; /**< All events that are associated with application context procedures of store, load, and deletion have this as event parameter. */
dm_service_context_t * p_service_context; /**< All events that are associated with service context procedures of store, load and deletion have this as event parameter. */
dm_device_context_t * p_device_context; /**< All events that are associated with device context procedures of store, load and deletion have this as event parameter. */
} dm_event_param_t;
/**
* @brief Asynchronous events details notified to the application by the module.
*
* @details Defines event type along with event parameters notified to the application by the
* module.
*/
typedef struct
{
uint8_t event_id; /**< Identifies the event. See \ref dm_events for details on event types and their significance. */
dm_event_param_t event_param; /**< Event parameters. Can be NULL if the event does not have any parameters. */
uint16_t event_paramlen; /**< Length of the event parameters, is zero if the event does not have any parameters. */
} dm_event_t;
/**
* @brief Event notification callback registered by application with the module.
*
* @details Event notification callback registered by application with the module when registering
* the module using \ref dm_register API.
*
* @param[in] p_handle Identifies the peer for which the event is being notified.
* @param[in] p_event Identifies the event, any associated parameters and parameter length.
* See \ref dm_events for details on event types and their significance.
* @param[in,out] event_result Provide additional information on the event.
* In addition to SDK error codes there is also a return value
* indicating if maximum number of connections has been reached when connecting or bonding.
*
* @retval NRF_SUCCESS on success, or a failure to indicate if it could handle the event
* successfully. There is no action taken in case application returns a failure.
*/
typedef ret_code_t (*dm_event_cb_t)(dm_handle_t const * p_handle,
dm_event_t const * p_event,
ret_code_t event_result);
/**
* @brief Initialization Parameters.
*
* @details Indicates the application parameters. Currently this only encompasses clearing
* all persistent data.
*/
typedef struct
{
bool clear_persistent_data; /**< Set to true in case the module should clear all persistent data. */
} dm_init_param_t;
/**
* @brief Application Registration Parameters.
*
* @details Parameters needed by the module when registering with it.
*/
typedef struct
{
dm_event_cb_t evt_handler; /**< Event Handler to be registered. It will receive asynchronous notification from the module, see \ref dm_events for asynchronous events. */
uint8_t service_type; /**< Bit mask identifying services that the application intends to support for all peers. */
ble_gap_sec_params_t sec_param; /**< Security parameters to be used for the application. */
} dm_application_param_t;
/**
* @brief Defines possible security status/states.
*
* @details Defines possible security status/states of a link when requested by application using
* the \ref dm_security_status_req.
*/
typedef enum
{
NOT_ENCRYPTED, /**< The link is not secured. */
ENCRYPTION_IN_PROGRESS, /**< Link security is being established.*/
ENCRYPTED /**< The link is secure.*/
} dm_security_status_t;
/** @} */
/**
* @defgroup dm_api Device Module APIs
*
* @brief This section describes APIs exposed by the module.
*
* @details This section describes APIs exposed by the module. The APIs have been categorized to provide
* better and specific look up for developers. Categories are:
* - Set up APIs.
* - Context Management APIs.
* - Utility APIs.
*
* MSCs describe usage of these APIs.
* See @ref dm_msc.
* @{
*/
/**
* @defgroup dm_setup_api Device Module Set-up APIs
*
* @brief Initialization & registration APIs that are pre-requisite for all other module procedures.
* @details This section describes the Module Initialization and Registration APIs needed to be set up by
* the application before device manager can start managing devices and device contexts
* for the application.
*
* @{
*/
/**
* @brief Module Initialization Routine.
*
* @details Function for initializing the module. Must called before any other APIs of the module are used.
*
* @param[in] p_init_param Initialization parameters.
*
* @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
*
* @note It is mandatory that pstorage is initialized before initializing this module.
*/
ret_code_t dm_init(dm_init_param_t const * p_init_param);
/**
* @brief Function for registering the application.
*
* @details This routine is used by the application to register for asynchronous events with the
* device manager. During registration the application also indicates the services that it
* intends to support on this instance. It is possible to register multiple times with the
* device manager. At least one instance shall be registered with the device manager after
* the module has been initialized.
* Maximum number of application instances device manager can support is determined
* by DM_MAX_APPLICATIONS.
*
* All applications must be registered before initiating or accepting connections from the peer.
*
* @param[in] p_appl_param Application parameters.
* @param[out] p_appl_instance Application Instance Identifier in case registration is successful.
*
* @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
* @retval NRF_ERROR_INVALID_STATE If the API is called without module initialization.
* @retval NRF_ERROR_NO_MEM If module cannot support more applications.
*
* @note Currently only one application instance is supported by the module.
*/
ret_code_t dm_register(dm_application_instance_t * p_appl_instance,
dm_application_param_t const * p_appl_param);
/**
* @brief Function for handling BLE events.
*
* @details BLE Event Handler for the module. This routine should be called from BLE stack event
* dispatcher for the module to work as expected.
*
* @param[in] p_ble_evt BLE stack event being dispatched to the function.
*
*/
void dm_ble_evt_handler(ble_evt_t * p_ble_evt);
/** @} */
/**
* @defgroup dm_security_api APIs to set up or read status of security on a link.
*
* @brief This section describes APIs to set up Security. These APIs require that the peer is
* connected before the procedures can be requested.
*
* @details This group allows application to request security procedures
* or get the status of the security on a link.
* @{
*/
/**
* @brief Function for requesting setting up security on a link.
*
* @details This API initiates security procedures with a peer device.
* @note For the GAP Central role, in case peer is not bonded, request to bond/pair is
* initiated. If it is bonded, the link is re-encrypted using the existing bond information.
* For the GAP peripheral role, a Slave security request is sent.
* @details If a pairing procedure is initiated successfully, application is notified of
* @ref DM_EVT_SECURITY_SETUP_COMPLETE. A result indicating success or failure is notified along with the event.
* In case the link is re-encrypted using existing bond information, @ref DM_EVT_LINK_SECURED is
* notified to the application.
*
* @param[in] p_handle Identifies the link on which security is desired.
*
* @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
* @retval NRF_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
* @retval NRF_ERROR_NULL If p_handle is NULL.
* @retval NRF_ERROR_INVALID_ADDR If the peer is not identified by the handle provided by the application
* or if the peer is not connected when this procedure is requested.
*/
ret_code_t dm_security_setup_req(dm_handle_t * p_handle);
/**
* @brief Function for reading the status of the security on a link.
*
* @details This API allows application to query status of security on a link.
*
* @param[in] p_handle Identifies the link on which security is desired.
* @param[out] p_status Pointer where security status is provided to the application.
* See \ref dm_security_status_t for possible statuses that can be expected.
*
* @retval NRF_SUCCESS Or appropriate error code indicating reason for failure.
* @retval NRF_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
* @retval NRF_ERROR_NULL If p_handle or p_status is NULL.
* @retval NRF_ERROR_INVALID_ADDR If peer is not identified by the handle provided by the application
* or if peer is not connected when this procedure is requested.
*/
ret_code_t dm_security_status_req(dm_handle_t const * p_handle, dm_security_status_t * p_status);
/**
* @brief Function for creating the whitelist.
*
* @details This API allows application to create whitelist based on bonded peer devices in module
* data base.
*
* @param[in] p_handle Identifies the application requesting whitelist creation.
* @param[in,out] p_whitelist Pointer where created whitelist is provided to the application.
*
* @note 'addr_count' and 'irk_count' fields of the structure should be populated with the maximum
* number of devices that the application wishes to request in the whitelist.
* If the number of bonded devices is less than requested, the fields are updated with that number of devices.
* If the number of devices are more than requested, the module will populate the list
* with devices in the order the bond was established with the peer devices. Also, if this routine is
* called when a connection exists with one or more peer devices,
* those connected devices are not added to the whitelist.
*
* @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
* @retval NRF_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
* @retval NRF_ERROR_NULL If p_handle or p_whitelist is NULL.
*/
ret_code_t dm_whitelist_create(dm_application_instance_t const * p_handle,
ble_gap_whitelist_t * p_whitelist);
/** @} */
/**
* @defgroup dm_cntxt_mgmt_api Context Management APIs
*
* @brief Utility APIs offered by the device manager to get information about the peer if and
* when needed.
*
* @details This group of API allow the application to access information that is not required to be
* maintained by the application but may be needed. Hence it is possible to get the
* information from the module instead of mapping all the information with a device
* context.
* @{
*/
ret_code_t dm_device_add(dm_handle_t * p_handle,
dm_device_context_t const * p_context);
/**
* @brief Function for deleting a peer device context and all related information from the database.
*
* @details Delete peer device context and all related information from database. If
* this API returns NRF_SUCCESS, DM_EVT_DEVICE_CONTEXT_DELETED event is notified to the
* application. Event result notified along with the event indicates success or failure
* of this procedure.
*
* @param[in] p_handle Identifies the peer device to be deleted.
*
* @retval NRF_SUCCESS on success, else an error code indicating reason for failure.
* @retval NRF_ERROR_INVALID_STATE In the API is called without module initialization and/or
* application registration.
* @retval NRF_ERROR_NULL If p_handle is NULL.
* @retval NRF_ERROR_INVALID_ADDR If peer is not identified the handle provided by the application.
*
* @note Deleting device context results in deleting service and application context for the
* bonded device. The respective events DM_EVT_SERVICE_CONTEXT_DELETED and
* DM_EVT_APPL_CONTEXT_DELETED are not notified to the application.
*/
ret_code_t dm_device_delete(dm_handle_t const * p_handle);
/**
* @brief Function for deleting all peer device context and all related information from the database.
*
* @details Delete peer device context and all related information from database. If
* this API returns NRF_SUCCESS, DM_EVT_DEVICE_CONTEXT_DELETED event is notified to the
* application for each device that is deleted from the data base. Event result
* notified along with the event indicates success or failure of this procedure.
*
* @param[in] p_handle Identifies application instance that is requesting
* the deletion of all bonded devices.
*
* @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
* @retval NRF_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
* @retval NRF_ERROR_NULL If p_handle is NULL.
* @retval NRF_ERROR_INVALID_ADDR If peer is not identified the handle provided by the application.
*
* @note Deleting device context results in deleting both service and application context for the
* bonded device. The respective events DM_EVT_SERVICE_CONTEXT_DELETED and
* DM_EVT_APPL_CONTEXT_DELETED are not notified to the application.
*/
ret_code_t dm_device_delete_all(dm_application_instance_t const * p_handle);
/**
* @brief Function for setting Service Context for a peer device identified by 'p_handle' parameter.
*
* @details This API allows application to Set Service Context for a peer device identified by the
* 'p_handle' parameter. This API is useful when the Service Context cannot be requested
* from the SoftDevice, but needs to be assembled by the application or an another module.
* (or when service context is exchanged in an out of band way.)
* This API could also be used to trigger a storing of service context into persistent
* memory. If this is desired, a NULL pointer could be passed to the p_context.
*
* @param[in] p_handle Identifies peer device for which the procedure is requested.
* @param[in] p_context Service context being set. The context information includes length of
* data and pointer to the contextual data being set. The memory pointed to by
* the pointer to data is assumed to be resident when API is being called and
* can be freed or reused once the set procedure is complete. Set procedure
* completion is indicated by the event \ref DM_EVT_SERVICE_CONTEXT_STORED.
* The Event result is notified along with the event and indicates success or failure of
* this procedure.
*
* @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
* @retval NRF_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
* @retval NRF_ERROR_NULL If p_handle is NULL.
* @retval NRF_ERROR_INVALID_ADDR If the peer is not identified by the handle provided by the application.
*/
ret_code_t dm_service_context_set(dm_handle_t const * p_handle,
dm_service_context_t const * p_context);
/**
* @brief Function for getting Service Context for a peer device identified by 'p_handle' parameter.
*
* @details Get Service Context for a peer device identified by the 'p_handle' parameter. If
* this API returns NRF_SUCCESS, DM_EVT_SERVICE_CONTEXT_LOADED event is notified to the
* application. The event result is notified along with the event indicates success or failure
* of this procedure.
*
* @param[in] p_handle Identifies peer device for which procedure is requested.
* @param[in] p_context Application context being requested. The context information includes length
* of the data and a pointer to the data. Note that requesting a 'get'
* of application does not need to provide memory, the pointer to data will be
* pointing to service data and hence no data movement is involved.
*
* @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
* @retval NRF_ERROR_INVALID_STATE In case API is called without module initialization and/or
* application registration.
* @retval NRF_ERROR_NULL If p_handle is NULL.
* @retval NRF_ERROR_INVALID_ADDR If the peer is not identified by the handle provided by the application.
*/
ret_code_t dm_service_context_get(dm_handle_t const * p_handle,
dm_service_context_t * p_context);
/**
* @brief Function for deleting a Service Context for a peer device identified by the 'p_handle' parameter.
*
* @details This API allows application to delete a Service Context identified for a peer device
* identified by the 'p_handle' parameter. If this API returns NRF_SUCCESS,
* DM_EVT_SERVICE_CONTEXT_DELETED event is notified to the application.
* Event result is notified along with the event and indicates success or failure of this
* procedure.
*
* @param[in] p_handle Identifies peer device for which procedure is requested.
*
* @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
* @retval NRF_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
* @retval NRF_ERROR_NULL If p_handle is NULL.
* @retval NRF_ERROR_INVALID_ADDR If the peer is not identified by the handle provided by the application.
*/
ret_code_t dm_service_context_delete(dm_handle_t const * p_handle);
/**
* @brief Function for setting Application Context for a peer device identified by the 'p_handle' parameter.
*
* @details This application allows the setting of the application context for the peer device identified by
* the 'p_handle'. Application context is stored persistently by the module and can be
* requested by the application at any time using the \ref dm_application_context_get
* API. Note that this procedure is permitted only for bonded devices. If the
* device is not bonded, application context cannot be set. However, it is not mandatory
* that the bonded device is connected when requesting this procedure.
*
* @param[in] p_handle Identifies peer device for which procedure is requested.
*
* @param[in] p_context Application context being set. The context information includes length of the
* data and pointer to the contextual data being set. The memory pointed to by
* the data pointer is assumed to be resident when API is being called and
* can be freed or reused once the set procedure is complete. Set procedure
* completion is notified by the event \ref DM_EVT_APPL_CONTEXT_STORED.
* The event result is notified along with the event and indicates success or
* failure of this procedure.
*
* @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
* @retval NRF_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
* @retval NRF_ERROR_NULL If p_handle and/or p_context is NULL.
* @retval NRF_ERROR_INVALID_ADDR If peer is not identified the handle provided by the application.
*
* @note The API returns FEATURE_NOT_ENABLED in case DEVICE_MANAGER_APP_CONTEXT_SIZE is set to zero.
*/
ret_code_t dm_application_context_set(dm_handle_t const * p_handle,
dm_application_context_t const * p_context);
/**
* @brief Function for getting Application Context for a peer device identified by the 'p_handle' parameter.
*
* @details Get Application Context for a peer device identified by the 'p_handle' parameter. If
* this API returns NRF_SUCCESS, DM_EVT_APPL_CONTEXT_LOADED event is notified to the
* application. Event result notified along with the event indicates success or failure
* of this procedure.
*
* @param[in] p_handle Identifies peer device for which procedure is requested.
* @param[in] p_context Application context being requested. The context information includes
* length of data and pointer to the contextual data is provided.
*
* @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
* @retval NRF_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
* @retval NRF_ERROR_NULL If p_handle and/or p_context is NULL.
* @retval NRF_ERROR_INVALID_ADDR If the peer is not identified by the handle provided by the application.
* @retval DM_NO_APP_CONTEXT If no application context was set that can be fetched.
*
* @note The API returns FEATURE_NOT_ENABLED in case DEVICE_MANAGER_APP_CONTEXT_SIZE is set to
* zero.
*/
ret_code_t dm_application_context_get(dm_handle_t const * p_handle,
dm_application_context_t * p_context);
/**
* @brief Function for deleting Application Context for a peer device identified by the 'p_handle' parameter.
*
* @details Delete Application Context for a peer device identified by the 'p_handle' parameter. If
* this API returns NRF_SUCCESS, DM_EVT_APPL_CONTEXT_DELETED event is notified to the
* application. The event result notified along with the event and indicates success or failure
* of this procedure.
*
* @param[in] p_handle Identifies peer device for which procedure is requested.
*
* @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
* @retval NRF_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
* @retval NRF_ERROR_NULL If the p_handle is NULL.
* @retval NRF_ERROR_INVALID_ADDR If peer is not identified the handle provided by the application.
* @retval DM_NO_APP_CONTEXT If no application context was set that can be deleted.
*
* @note The API returns FEATURE_NOT_ENABLED if the DEVICE_MANAGER_APP_CONTEXT_SIZE is set to zero.
*/
ret_code_t dm_application_context_delete(dm_handle_t const * p_handle);
/** @} */
/**
* @defgroup utility_api Utility APIs
* @{
* @brief This section describes the utility APIs offered by the module.
*
* @details APIs defined in this section are utility or assisting/helper APIs.
*/
/**
* @brief Function for Setting/Copying Application instance to Device Manager handle.
*
* @param[in] p_appl_instance Application instance to be set.
* @param[out] p_handle Device Manager handle for which the instance is to be copied.
*
* @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
* @retval NRF_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
* @retval NRF_ERROR_NULL If p_handle and/or p_addr is NULL.
*/
ret_code_t dm_application_instance_set(dm_application_instance_t const * p_appl_instance,
dm_handle_t * p_handle);
/**
* @brief Function for getting a peer's device address.
*
* @param[in] p_handle Identifies the peer device whose address is requested. Can not be NULL.
* @param[out] p_addr Pointer where address is to be copied. Can not be NULL.
*
* @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
* @retval NRF_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
* @retval NRF_ERROR_NULL If p_handle and/or p_addr is NULL.
* @retval NRF_ERROR_NOT_FOUND If the peer could not be identified.
*/
ret_code_t dm_peer_addr_get(dm_handle_t const * p_handle,
ble_gap_addr_t * p_addr);
/**
* @brief Function for setting/updating a peer's device address.
*
* @param[in] p_handle Identifies the peer device whose address is requested to be set/updated.
* @param[out] p_addr Address to be set/updated.
*
* @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
* @retval NRF_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
* @retval NRF_ERROR_NULL If p_handle and/or p_addr is NULL.
* @retval NRF_ERROR_INVALID_ADDR If the peer is not identified by the handle provided by the application.
* @retval NRF_ERROR_INVALID_PARAM If this procedure is requested while connected to the peer or if the address
* type was set to BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE.
*
* @note Setting or updating a peer's device address is permitted
* only for a peer that is bonded and disconnected.
* @note Updated address is reflected only after DM_EVT_DEVICE_CONTEXT_STORED is notified to the
* application for this bonded device instance. In order to avoid abnormal behaviour, it is
* recommended to not invite/initiate connections on the updated address unless this event
* has been notified.
*/
ret_code_t dm_peer_addr_set(dm_handle_t const * p_handle,
ble_gap_addr_t const * p_addr);
/**
* @brief Function for initializing Device Manager handle.
*
* @param[in] p_handle Device Manager handle to be initialized.
*
* @retval NRF_SUCCESS On success.
* @retval NRF_ERROR_NULL If p_handle is NULL.
*
* @note This routine is permitted before initialization of the module.
*/
ret_code_t dm_handle_initialize(dm_handle_t * p_handle);
/**
* @brief Function for getting distributed keys for a device.
*
* @param[in] p_handle Device Manager handle identifying the peer.
* @param[out] p_key_dist Pointer to distributed keys.
*
* @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
* @retval NRF_ERROR_INVALID_STATE If the API is called without module initialization and/or
* application registration.
* @retval NRF_ERROR_NULL If the p_handle and/or p_key_dist pointer is NULL.
* @retval NRF_ERROR_INVALID_ADDR If the peer is not identified by the handle provided by the application.
*/
ret_code_t dm_distributed_keys_get(dm_handle_t const * p_handle,
dm_sec_keyset_t * p_key_dist);
/**
* @brief Function for getting the corresponding dm_handle_t based on the connection handle.
*
* @param[in] conn_handle Connection handle as provided by the SoftDevice.
* @param[in,out] p_handle Pointer to the p_handle containg the application instance for the
* registered application. If the application instance is valid then
* the p_handle will be filled with requested data.
*
* @retval NRF_SUCCESS On success, else an error code indicating reason for failure.
* @retval NRF_ERROR_NULL If the p_handle pointer is NULL.
* @retval NRF_ERROR_NOT_FOUND If no p_handle is found for the provided connection handle.
*/
ret_code_t dm_handle_get(uint16_t conn_handle, dm_handle_t * p_handle);
/** @} */
/** @} */
/** @} */
#endif // DEVICE_MANAGER_H__

View File

@ -1,595 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "gatt_cache_manager.h"
#include "nrf_ble_gap.h"
#include "ble_conn_state.h"
#include "peer_manager_types.h"
#include "peer_manager_internal.h"
#include "peer_database.h"
#include "id_manager.h"
#include "security_dispatcher.h"
#include "gatts_cache_manager.h"
#include "gattc_cache_manager.h"
#include "sdk_common.h"
/**@brief Structure containing the module variable(s) of the GCM module.
*/
typedef struct
{
gcm_evt_handler_t evt_handler; /**< The event handler to use for outbound GSCM events. */
ble_conn_state_user_flag_id_t flag_id_local_db_update_pending; /**< Flag ID for flag collection to keep track of which connections need a local DB update procedure. */
ble_conn_state_user_flag_id_t flag_id_local_db_apply_pending; /**< Flag ID for flag collection to keep track of which connections need a local DB apply procedure. */
ble_conn_state_user_flag_id_t flag_id_service_changed_pending; /**< Flag ID for flag collection to keep track of which connections need to be sent a service changed indication. */
ble_conn_state_user_flag_id_t flag_id_service_changed_sent; /**< Flag ID for flag collection to keep track of which connections have been sent a service changed indication and are waiting for a handle value confirmation. */
} gcm_t;
static gcm_t m_gcm; /**< Instantiation of module variable(s). */
#define MODULE_INITIALIZED (m_gcm.evt_handler != NULL)
#include "sdk_macros.h"
static void service_changed_pending_flags_check(void);
/**@brief Function for resetting the module variable(s) of the GSCM module.
*
* @param[out] The instance to reset.
*/
static void internal_state_reset(gcm_t * p_gcm)
{
memset(p_gcm, 0, sizeof(gcm_t));
}
/**@brief Function for checking a write event for whether a CCCD was written during the write
* operation.
*
* @param[in] p_write_evt The parameters of the write event.
*
* @return Whether the write was on a CCCD.
*/
static bool cccd_written(ble_gatts_evt_write_t * p_write_evt)
{
return ( (p_write_evt->op == BLE_GATTS_OP_WRITE_REQ)
&& (p_write_evt->uuid.type == BLE_UUID_TYPE_BLE)
&& (p_write_evt->uuid.uuid == BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG)
);
}
/**@brief Function for performing the local DB update procedure in an event context, where no return
* code can be given.
*
* @details This function will do the procedure, and check the result, set a flag if needed, and
* send an event if needed.
*
* @param[in] conn_handle The connection to perform the procedure on.
*/
static void local_db_apply_in_evt(uint16_t conn_handle)
{
bool set_procedure_as_pending = false;
ret_code_t err_code;
gcm_evt_t event;
if (conn_handle == BLE_CONN_HANDLE_INVALID)
{
return;
}
err_code = gscm_local_db_cache_apply(conn_handle);
switch(err_code)
{
case NRF_SUCCESS:
event.evt_id = GCM_EVT_LOCAL_DB_CACHE_APPLIED;
event.peer_id = im_peer_id_get_by_conn_handle(conn_handle);
event.params.local_db_cache_applied.conn_handle = conn_handle;
m_gcm.evt_handler(&event);
break;
case NRF_ERROR_BUSY:
set_procedure_as_pending = true;
break;
case NRF_ERROR_INVALID_DATA:
event.evt_id = GCM_EVT_ERROR_LOCAL_DB_CACHE_APPLY;
event.peer_id = im_peer_id_get_by_conn_handle(conn_handle);
event.params.error_local_db_cache_apply.conn_handle = conn_handle;
m_gcm.evt_handler(&event);
break;
case BLE_ERROR_INVALID_CONN_HANDLE:
/* Do nothing */
break;
default:
event.evt_id = GCM_EVT_ERROR_UNEXPECTED;
event.peer_id = im_peer_id_get_by_conn_handle(conn_handle);
event.params.error_unexpected.conn_handle = conn_handle;
event.params.error_unexpected.error = err_code;
m_gcm.evt_handler(&event);
break;
}
ble_conn_state_user_flag_set(conn_handle, m_gcm.flag_id_local_db_apply_pending, set_procedure_as_pending);
}
/**@brief Function for performing the local DB apply procedure in an event context, where no return
* code can be given.
*
* @details This function will do the procedure, and check the result, set a flag if needed, and
* send an event if needed.
*
* @param[in] conn_handle The connection to perform the procedure on.
*/
static void local_db_update_in_evt(uint16_t conn_handle)
{
gcm_evt_t event;
bool set_procedure_as_pending = false;
ret_code_t err_code = gscm_local_db_cache_update(conn_handle);
switch(err_code)
{
case NRF_SUCCESS:
event.evt_id = GCM_EVT_LOCAL_DB_CACHE_UPDATED;
event.params.local_db_cache_applied.conn_handle = conn_handle;
event.peer_id = im_peer_id_get_by_conn_handle(conn_handle);
m_gcm.evt_handler(&event);
break;
case BLE_ERROR_INVALID_CONN_HANDLE:
/* Do nothing */
break;
case NRF_ERROR_BUSY:
set_procedure_as_pending = true;
break;
case NRF_ERROR_DATA_SIZE:
event.evt_id = GCM_EVT_ERROR_DATA_SIZE;
event.params.error_data_size.conn_handle = conn_handle;
event.peer_id = im_peer_id_get_by_conn_handle(conn_handle);
m_gcm.evt_handler(&event);
break;
case NRF_ERROR_NO_MEM:
event.evt_id = GCM_EVT_ERROR_STORAGE_FULL;
event.params.error_no_mem.conn_handle = conn_handle;
event.peer_id = im_peer_id_get_by_conn_handle(conn_handle);
m_gcm.evt_handler(&event);
break;
default:
event.evt_id = GCM_EVT_ERROR_UNEXPECTED;
event.peer_id = im_peer_id_get_by_conn_handle(conn_handle);
event.params.error_unexpected.conn_handle = conn_handle;
event.params.error_unexpected.error = err_code;
m_gcm.evt_handler(&event);
break;
}
ble_conn_state_user_flag_set(conn_handle, m_gcm.flag_id_local_db_update_pending, set_procedure_as_pending);
}
/**@brief Function for sending a service changed indication in an event context, where no return
* code can be given.
*
* @details This function will do the procedure, and check the result, set a flag if needed, and
* send an event if needed.
*
* @param[in] conn_handle The connection to perform the procedure on.
*/
static void service_changed_send_in_evt(uint16_t conn_handle)
{
gcm_evt_t event;
bool sc_pending_state = true;
bool sc_sent_state = false;
ret_code_t err_code = gscm_service_changed_ind_send(conn_handle);
switch(err_code)
{
case NRF_SUCCESS:
sc_sent_state = true;
event.evt_id = GCM_EVT_SERVICE_CHANGED_IND_SENT;
event.peer_id = im_peer_id_get_by_conn_handle(conn_handle);
event.params.service_changed_ind_sent.conn_handle = conn_handle;
m_gcm.evt_handler(&event);
break;
case NRF_ERROR_BUSY:
// Do nothing.
break;
case NRF_ERROR_INVALID_STATE:
// CCCDs not enabled. Drop indication.
// Fallthrough.
case NRF_ERROR_NOT_SUPPORTED:
// Service changed not supported. Drop indication.
sc_pending_state = false;
gscm_db_change_notification_done(im_peer_id_get_by_conn_handle(conn_handle));
break;
case BLE_ERROR_GATTS_SYS_ATTR_MISSING:
local_db_apply_in_evt(conn_handle);
break;
case BLE_ERROR_INVALID_CONN_HANDLE:
// Do nothing.
break;
default:
event.evt_id = GCM_EVT_ERROR_UNEXPECTED;
event.params.error_unexpected.conn_handle = conn_handle;
event.params.error_unexpected.error = err_code;
event.peer_id = im_peer_id_get_by_conn_handle(conn_handle);
m_gcm.evt_handler(&event);
break;
}
ble_conn_state_user_flag_set(conn_handle, m_gcm.flag_id_service_changed_pending, sc_pending_state);
ble_conn_state_user_flag_set(conn_handle, m_gcm.flag_id_service_changed_sent, sc_sent_state);
}
/**@brief Callback function for events from the GATT Cache Server Manager module.
*
* @param[in] p_event The event from the GATT Cache Server Manager module.
*/
static void gscm_evt_handler(gscm_evt_t const * p_event)
{
gcm_evt_t event;
event.peer_id = p_event->peer_id;
switch (p_event->evt_id)
{
case GSCM_EVT_LOCAL_DB_CACHE_STORED:
event.evt_id = GCM_EVT_LOCAL_DB_CACHE_STORED;
m_gcm.evt_handler(&event);
local_db_apply_in_evt(im_conn_handle_get(p_event->peer_id));
break;
case GSCM_EVT_LOCAL_DB_CACHE_UPDATED:
event.evt_id = GCM_EVT_LOCAL_DB_CACHE_UPDATED;
event.params.local_db_cache_updated.conn_handle = p_event->params.local_db_cache_updated.conn_handle;
m_gcm.evt_handler(&event);
break;
case GSCM_EVT_SC_STATE_STORED:
if (p_event->params.sc_state_stored.state)
{
uint16_t conn_handle = im_conn_handle_get(p_event->peer_id);
if (conn_handle != BLE_CONN_HANDLE_INVALID)
{
ble_conn_state_user_flag_set(conn_handle, m_gcm.flag_id_service_changed_pending, true);
service_changed_pending_flags_check();
}
}
break;
}
}
/**@brief Callback function for events from the GATT Cache Client Manager module.
*
* @param[in] p_event The event from the GATT Cache Client Manager module.
*/
static void gccm_evt_handler(gccm_evt_t const * p_event)
{
}
/**@brief Callback function for events from the Identity Manager module.
*
* @param[in] p_event The event from the Identity Manager module.
*/
static void im_evt_handler(im_evt_t const * p_event)
{
switch (p_event->evt_id)
{
case IM_EVT_BONDED_PEER_CONNECTED:
local_db_apply_in_evt(p_event->conn_handle);
if (gscm_service_changed_ind_needed(p_event->conn_handle))
{
ble_conn_state_user_flag_set(p_event->conn_handle, m_gcm.flag_id_service_changed_pending, true);
}
break;
default:
break;
}
}
/**@brief Callback function for events from the Security Dispatcher module.
*
* @param[in] p_event The event from the Security Dispatcher module.
*/
static void smd_evt_handler(smd_evt_t const * p_event)
{
switch (p_event->evt_id)
{
case SMD_EVT_BONDING_INFO_STORED:
local_db_update_in_evt(p_event->conn_handle);
break;
default:
break;
}
}
ret_code_t gcm_init(gcm_evt_handler_t evt_handler)
{
VERIFY_PARAM_NOT_NULL(evt_handler);
ret_code_t err_code;
err_code = gscm_init(gscm_evt_handler);
VERIFY_SUCCESS(err_code);
err_code = gccm_init(gccm_evt_handler);
VERIFY_SUCCESS(err_code);
internal_state_reset(&m_gcm);
m_gcm.evt_handler = evt_handler;
err_code = im_register(im_evt_handler);
VERIFY_SUCCESS(err_code);
err_code = smd_register(smd_evt_handler);
VERIFY_SUCCESS(err_code);
m_gcm.flag_id_local_db_update_pending = ble_conn_state_user_flag_acquire();
m_gcm.flag_id_local_db_apply_pending = ble_conn_state_user_flag_acquire();
m_gcm.flag_id_service_changed_pending = ble_conn_state_user_flag_acquire();
m_gcm.flag_id_service_changed_sent = ble_conn_state_user_flag_acquire();
if ((m_gcm.flag_id_local_db_update_pending == BLE_CONN_STATE_USER_FLAG_INVALID)
|| (m_gcm.flag_id_local_db_apply_pending == BLE_CONN_STATE_USER_FLAG_INVALID)
|| (m_gcm.flag_id_service_changed_pending == BLE_CONN_STATE_USER_FLAG_INVALID)
|| (m_gcm.flag_id_service_changed_sent == BLE_CONN_STATE_USER_FLAG_INVALID))
{
err_code = NRF_ERROR_INTERNAL;
}
return err_code;
}
/**@brief Function for performing the Local DB apply procedure if it is pending on any connections.
*/
static void apply_pending_flags_check(void)
{
sdk_mapped_flags_t apply_pending_flags;
apply_pending_flags = ble_conn_state_user_flag_collection(m_gcm.flag_id_local_db_apply_pending);
if (sdk_mapped_flags_any_set(apply_pending_flags))
{
sdk_mapped_flags_key_list_t conn_handle_list;
conn_handle_list = ble_conn_state_conn_handles();
for (uint32_t i = 0; i < conn_handle_list.len; i++)
{
if (ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], m_gcm.flag_id_local_db_apply_pending))
{
local_db_apply_in_evt(conn_handle_list.flag_keys[i]);
}
}
}
}
/**@brief Function for performing the Local DB update procedure if it is pending on any connections.
*/
static void update_pending_flags_check(void)
{
sdk_mapped_flags_t update_pending_flags;
update_pending_flags = ble_conn_state_user_flag_collection(m_gcm.flag_id_local_db_update_pending);
if (sdk_mapped_flags_any_set(update_pending_flags))
{
sdk_mapped_flags_key_list_t conn_handle_list;
conn_handle_list = ble_conn_state_conn_handles();
for (uint32_t i = 0; i < conn_handle_list.len; i++)
{
if (ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], m_gcm.flag_id_local_db_update_pending))
{
local_db_update_in_evt(conn_handle_list.flag_keys[i]);
}
}
}
}
/**@brief Function for sending service changed indications if it is pending on any connections.
*/
static void service_changed_pending_flags_check(void)
{
sdk_mapped_flags_t service_changed_pending_flags;
service_changed_pending_flags = ble_conn_state_user_flag_collection(m_gcm.flag_id_service_changed_pending);
if (sdk_mapped_flags_any_set(service_changed_pending_flags))
{
sdk_mapped_flags_key_list_t conn_handle_list;
conn_handle_list = ble_conn_state_conn_handles();
for (uint32_t i = 0; i < conn_handle_list.len; i++)
{
if ( ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i],
m_gcm.flag_id_service_changed_pending)
&& !ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i],
m_gcm.flag_id_service_changed_sent))
{
service_changed_send_in_evt(conn_handle_list.flag_keys[i]);
}
}
}
}
/**@brief Callback function for BLE events from the SoftDevice.
*
* @param[in] p_ble_evt The BLE event from the SoftDevice.
*/
void gcm_ble_evt_handler(ble_evt_t * p_ble_evt)
{
gcm_evt_t event;
switch(p_ble_evt->header.evt_id)
{
case BLE_GATTS_EVT_SYS_ATTR_MISSING:
local_db_apply_in_evt(p_ble_evt->evt.gatts_evt.conn_handle);
break;
case BLE_GATTS_EVT_SC_CONFIRM:
event.evt_id = GCM_EVT_SERVICE_CHANGED_IND_CONFIRMED;
event.peer_id = im_peer_id_get_by_conn_handle(p_ble_evt->evt.gatts_evt.conn_handle);
event.params.service_changed_ind_sent.conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
gscm_db_change_notification_done(event.peer_id);
ble_conn_state_user_flag_set(p_ble_evt->evt.gatts_evt.conn_handle, m_gcm.flag_id_service_changed_pending, false);
m_gcm.evt_handler(&event);
break;
case BLE_GATTS_EVT_WRITE:
if (cccd_written(&p_ble_evt->evt.gatts_evt.params.write))
{
local_db_update_in_evt(p_ble_evt->evt.gatts_evt.conn_handle);
}
break;
}
apply_pending_flags_check();
update_pending_flags_check();
service_changed_pending_flags_check();
}
ret_code_t gcm_remote_db_store(pm_peer_id_t peer_id,
ble_gatt_db_srv_t * p_remote_db,
uint32_t n_services)
{
VERIFY_MODULE_INITIALIZED();
return gccm_remote_db_store(peer_id, p_remote_db, n_services);
}
ret_code_t gcm_remote_db_retrieve(pm_peer_id_t peer_id,
ble_gatt_db_srv_t * p_remote_db,
uint32_t * p_n_services)
{
VERIFY_MODULE_INITIALIZED();
VERIFY_PARAM_NOT_NULL(p_remote_db);
return gccm_remote_db_retrieve(peer_id, p_remote_db, p_n_services);
}
ret_code_t gcm_local_db_cache_update(uint16_t conn_handle)
{
VERIFY_MODULE_INITIALIZED();
ret_code_t err_code = gscm_local_db_cache_update(conn_handle);
bool set_procedure_as_pending = false;
if (err_code == NRF_ERROR_BUSY)
{
set_procedure_as_pending = true;
err_code = NRF_SUCCESS;
}
ble_conn_state_user_flag_set(conn_handle, m_gcm.flag_id_local_db_update_pending, set_procedure_as_pending);
return err_code;
}
ret_code_t gcm_local_db_cache_set(pm_peer_id_t peer_id, pm_peer_data_local_gatt_db_t * p_local_db)
{
VERIFY_MODULE_INITIALIZED();
return gscm_local_db_cache_set(peer_id, p_local_db);
}
ret_code_t gcm_local_db_cache_get(pm_peer_id_t peer_id, pm_peer_data_local_gatt_db_t * p_local_db)
{
VERIFY_MODULE_INITIALIZED();
return gscm_local_db_cache_get(peer_id, p_local_db);
}
void gcm_local_database_has_changed(void)
{
gscm_local_database_has_changed();
sdk_mapped_flags_key_list_t conn_handles = ble_conn_state_conn_handles();
for (uint16_t i = 0; i < conn_handles.len; i++)
{
if (im_peer_id_get_by_conn_handle(conn_handles.flag_keys[i]) == PM_PEER_ID_INVALID)
{
ble_conn_state_user_flag_set(conn_handles.flag_keys[i], m_gcm.flag_id_service_changed_pending, true);
}
}
service_changed_pending_flags_check();
}

View File

@ -1,236 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 GATT_CACHE_MANAGER_H__
#define GATT_CACHE_MANAGER_H__
#include <stdint.h>
#include "sdk_errors.h"
#include "nrf_ble.h"
#include "nrf_ble_gap.h"
#include "peer_manager_types.h"
/**
* @cond NO_DOXYGEN
* @defgroup gatt_cache_manager GATT Cache Manager
* @ingroup peer_manager
* @{
* @brief An internal module of @ref peer_manager. A module for managing persistent storing of GATT
* attributes.
*/
/**@brief Events that can come from the GATT Cache Manager module.
*/
typedef enum
{
GCM_EVT_LOCAL_DB_CACHE_STORED, /**< The persistent cache for the local database has been updated with provided values, for one peer. */
GCM_EVT_LOCAL_DB_CACHE_UPDATED, /**< The persistent cache for the local database has been updated with values from the SoftDevice, for one peer. */
GCM_EVT_LOCAL_DB_CACHE_APPLIED, /**< The SoftDevice has been given local database values from the persistent cache, for one peer. */
GCM_EVT_ERROR_LOCAL_DB_CACHE_APPLY, /**< The stored local database values for a peer were rejected by the SoftDevice, which means the database has changed. */
GCM_EVT_REMOTE_DB_CACHE_UPDATED, /**< The persistent cache for the remote database has been updated with provided values, for one peer. */
GCM_EVT_SERVICE_CHANGED_IND_SENT, /**< A service changed indication has been sent to a peer. */
GCM_EVT_SERVICE_CHANGED_IND_CONFIRMED, /**< A sent service changed indication has been confirmed by a peer. */
GCM_EVT_ERROR_DATA_SIZE, /**< An operation failed because the write buffer of the Peer Database module was not large enough. This is a fatal error. */
GCM_EVT_ERROR_STORAGE_FULL, /**< An operation failed because there was no available storage room in persistent storage. Please free up room, and the operation will automatically continue. */
GCM_EVT_ERROR_UNEXPECTED, /**< An operation failed with an unexpected error. The error is provided. This is possibly a fatal error. */
} gcm_evt_id_t;
/**@brief A structure meant to be used for event parameters for multiple event types.
*/
typedef struct
{
uint16_t conn_handle; /**< The connection handle. Likely the connection handle an event pertains to. */
} gcm_evt_param_conn_handle_t;
/**@brief Structure containing an event from the GCM module.
*/
typedef struct
{
gcm_evt_id_t evt_id; /**< The type of event this is. */
pm_peer_id_t peer_id; /**< The peer ID this event pertains to. */
union
{
gcm_evt_param_conn_handle_t local_db_cache_updated;
gcm_evt_param_conn_handle_t local_db_cache_applied;
gcm_evt_param_conn_handle_t error_local_db_cache_apply;
gcm_evt_param_conn_handle_t service_changed_ind_sent;
gcm_evt_param_conn_handle_t service_changed_ind_confirmed;
gcm_evt_param_conn_handle_t error_data_size;
gcm_evt_param_conn_handle_t error_no_mem;
struct
{
uint16_t conn_handle; /**< The handle of the connection the event pertains to. */
ret_code_t error; /**< The unexpected error that occurred. */
} error_unexpected;
} params; /**< Event specific parameters. Chosen based on evt_id. */
} gcm_evt_t;
/**@brief Event handler for events from the GATT Cache Manager module.
*
* @param[in] event The event that has happened.
* @param[in] peer The id of the peer the event pertains to.
* @param[in] flags The data the event pertains to.
*/
typedef void (*gcm_evt_handler_t)(gcm_evt_t const * p_event);
/**@brief Function for initializing the GATT Cache Manager module.
*
* @param[in] evt_handler Callback for events from the GATT Cache Manager module.
*
* @retval NRF_SUCCESS Initialization was successful.
* @retval NRF_ERROR_NULL evt_handler was NULL.
*/
ret_code_t gcm_init(gcm_evt_handler_t evt_handler);
/**@brief Function for dispatching SoftDevice events to the GATT Cache Manager module.
*
* @param[in] p_ble_evt The SoftDevice event.
*/
void gcm_ble_evt_handler(ble_evt_t * p_ble_evt);
/**@brief Function for storing a discovered remote database persistently.
*
* @param[in] peer_id Peer to store the database for.
* @param[in] p_remote_db Database values to store as an array. Can be NULL if n_services is 0.
* @param[in] n_services Number of services in p_remote_db array. If 0, values are cleared.
*
* @retval NRF_SUCCESS Store procedure successfully started.
* @retval NRF_ERROR_NOT_FOUND The peer id is invalid or unallocated.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t gcm_remote_db_store(pm_peer_id_t peer_id,
ble_gatt_db_srv_t * p_remote_db,
uint32_t n_services);
/**@brief Function for retrieving a persistently stored remote database.
*
* @param[in] peer_id Peer to retrieve data for.
* @param[out] p_remote_db If p_n_services was large enough: Copied database values.
* @param[inout] p_n_services In: Size of provided p_remote_db array. Out: Size of data in flash.
*
* @note p_n_services is always updated with the size of the data to be retrieved. The data is only
* copied if p_remote_db is large enough (p_n_services is large enough initially).
*
* @retval NRF_SUCCESS Data retrieved successfully.
* @retval NRF_ERROR_NOT_FOUND The peer ID is invalid or unallocated.
* @retval NRF_ERROR_NULL p_remote_db is NULL.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t gcm_remote_db_retrieve(pm_peer_id_t peer_id,
ble_gatt_db_srv_t * p_remote_db,
uint32_t * p_n_services);
/**@brief Function for triggering local GATT database data to be stored persistently. Values are
* retrieved from SoftDevice and written to persistent storage.
*
* @note This function is only needed when you want to override the regular functionality of the
* module, e.g. to immediately store to flash instead of waiting for the native logic to
* perform the update.
*
* @param[in] conn_handle Connection handle to perform update on.
*
* @retval NRF_SUCCESS Store operation started.
* @retval BLE_ERROR_INVALID_CONN_HANDLE conn_handle does not refer to an active, bonded connection.
* @retval NRF_ERROR_DATA_SIZE Write buffer not large enough. Call will never work with
* this GATT database.
* @retval NRF_ERROR_NO_MEM No room in persistent_storage. Free up space; the
* operation will be automatically reattempted after the
* next compression procedure
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t gcm_local_db_cache_update(uint16_t conn_handle);
/**@brief Function for setting new values in the local database cache.
*
* @note If the peer is connected, the values will also be applied immediately to the connection.
* @note This function is only needed when you want to override the regular functionality of the
* module.
* @note The data in the pointer must be available until the GCM_EVT_LOCAL_DB_CACHE_SET event is
* received.
*
* @param[in] peer_id Peer to set values for.
* @param[in] p_local_db Database values to apply. If NULL, the values will instead be cleared.
*
* @retval NRF_SUCCESS Operation started, and values were applied (if connected).
* @retval NRF_ERROR_NOT_FOUND The peer ID was invalid or unallocated.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t gcm_local_db_cache_set(pm_peer_id_t peer_id, pm_peer_data_local_gatt_db_t * p_local_db);
/**@brief Function for retrieving values in the local database cache.
*
* @note This function is not needed for regular operation of the module.
*
* @param[in] peer_id Peer to get values for.
* @param[out] p_local_db Database values.
*
* @retval NRF_SUCCESS Values retrieved successfully.
* @retval NRF_ERROR_NOT_FOUND The peer ID was invalid or unallocated.
* @retval NRF_ERROR_NULL p_local_db was NULL.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t gcm_local_db_cache_get(pm_peer_id_t peer_id, pm_peer_data_local_gatt_db_t * p_local_db);
/**@brief Function for manually informing that the local database has changed.
*
* @details This causes a service changed notification to be sent to all bonded peers that
* subscribe to it.
*/
void gcm_local_database_has_changed(void);
/** @}
* @endcond
*/
#endif /* GATT_CACHE_MANAGER_H__ */

View File

@ -1,139 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "gattc_cache_manager.h"
#include "nrf_ble_gap.h"
#include "ble_conn_state.h"
#include "peer_manager_types.h"
#include "peer_database.h"
#include "id_manager.h"
#include "sdk_common.h"
#define MAX_SIMUL_SEC_PROCEDURES 2
typedef struct
{
gccm_evt_handler_t evt_handler;
} gccm_t;
static gccm_t m_gccm;
#define MODULE_INITIALIZED (m_gccm.evt_handler != NULL)
#include "sdk_macros.h"
static void internal_state_reset(gccm_t * gccm)
{
memset(gccm, 0, sizeof(gccm_t));
}
/**@brief Event handler for events from the peer_database module.
*
* @param[in] p_event The event that has happend with peer id and flags.
*/
static void pdb_evt_handler(pdb_evt_t const * p_event)
{
gccm_evt_t gccm_evt;
gccm_evt.evt_id = GCCM_EVT_REMOTE_DB_STORED;
gccm_evt.peer_id = p_event->peer_id;
m_gccm.evt_handler(&gccm_evt);
}
ret_code_t gccm_init(gccm_evt_handler_t evt_handler)
{
ret_code_t err_code;
if (evt_handler == NULL)
{
err_code = NRF_ERROR_NULL;
}
else
{
err_code = pdb_register(pdb_evt_handler);
if (err_code == NRF_SUCCESS)
{
internal_state_reset(&m_gccm);
m_gccm.evt_handler = evt_handler;
}
}
return err_code;
}
ret_code_t gccm_remote_db_store(pm_peer_id_t peer_id,
ble_gatt_db_srv_t * p_remote_db,
uint32_t n_services)
{
VERIFY_MODULE_INITIALIZED();
VERIFY_PARAM_NOT_NULL(p_remote_db);
// Initialize the peer_data
pm_peer_data_const_t peer_data;
memset(&peer_data, 0, sizeof(peer_data));
peer_data.data_id = PM_PEER_DATA_ID_GATT_REMOTE;
peer_data.p_remote_gatt_db = p_remote_db;
peer_data.length_words = PM_REMOTE_DB_N_WORDS(n_services);
return pdb_raw_store(peer_id, &peer_data, NULL);
}
ret_code_t gccm_remote_db_retrieve(pm_peer_id_t peer_id,
ble_gatt_db_srv_t * p_remote_db,
uint32_t * p_n_services)
{
VERIFY_MODULE_INITIALIZED();
VERIFY_PARAM_NOT_NULL(p_remote_db);
VERIFY_PARAM_NOT_NULL(p_n_services);
// Initialize the peer_data
pm_peer_data_t peer_data;
memset(&peer_data, 0, sizeof(peer_data));
peer_data.data_id = PM_PEER_DATA_ID_GATT_REMOTE;
peer_data.p_remote_gatt_db = p_remote_db;
peer_data.length_words = PM_REMOTE_DB_N_WORDS(*p_n_services);
ret_code_t err_code = pdb_raw_read(peer_id, PM_PEER_DATA_ID_GATT_REMOTE, &peer_data);
*p_n_services = PM_REMOTE_DB_N_SERVICES(peer_data.length_words);
return err_code;
}

View File

@ -1,132 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 GATTC_CACHE_MANAGER_H__
#define GATTC_CACHE_MANAGER_H__
#include <stdint.h>
#include "sdk_errors.h"
#include "nrf_ble.h"
#include "nrf_ble_gap.h"
#include "peer_manager_types.h"
/**
* @cond NO_DOXYGEN
* @defgroup gattc_cache_manager GATT Client Cache Manager
* @ingroup peer_manager
* @{
* @brief An internal module of @ref peer_manager. A module for managing persistent storing of GATT
* attributes pertaining to the GATT client role of the local device.
*/
/**@brief Events that can come from the GATT Cache Manager module.
*/
typedef enum
{
GCCM_EVT_REMOTE_DB_UPDATED, /**< Values for the specified data has been updated in persistent storage. */
GCCM_EVT_REMOTE_DB_STORED, /**< New values for the specified data has been written in persistent storage. */
} gccm_evt_id_t;
typedef struct
{
gccm_evt_id_t evt_id;
pm_peer_id_t peer_id;
} gccm_evt_t;
/**@brief Event handler for events from the GATT Client Cache Manager module.
*
* @param[in] event The event that has happened.
* @param[in] peer The id of the peer the event pertains to.
* @param[in] flags The data the event pertains to.
*/
typedef void (*gccm_evt_handler_t)(gccm_evt_t const * p_event);
/**@brief Function for initializing the GATT Client Cache Manager module.
*
* @param[in] evt_handler Callback for events from the GATT Client Cache Manager module.
*
* @retval NRF_SUCCESS Initialization was successful.
* @retval NRF_ERROR_NULL evt_handler was NULL.
*/
ret_code_t gccm_init(gccm_evt_handler_t evt_handler);
/**@brief Function for storing a discovered remote database persistently.
*
* @param[in] peer_id Peer to store the database for.
* @param[in] p_remote_db Database values to store as an array. Can be NULL if n_services is 0.
* @param[in] n_services Number of services in p_remote_db array. If 0, values are cleared.
*
* @retval NRF_SUCCESS Store procedure successfully started.
* @retval NRF_ERROR_NOT_FOUND The peer id is invalid or unallocated.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t gccm_remote_db_store(pm_peer_id_t peer_id,
ble_gatt_db_srv_t * p_remote_db,
uint32_t n_services);
/**@brief Function for retrieving a persistently stored remote database.
*
* @param[in] peer_id Peer to retrieve data for.
* @param[out] p_remote_db If p_n_services was large enough: Copied database values.
* @param[inout] p_n_services In: Size of provided p_remote_db array. Out: Size of data in flash.
*
* @note p_n_services is always updated with the size of the data to be retrieved. The data is only
* copied if p_remote_db is large enough (p_n_services is large enough initially).
*
* @retval NRF_SUCCESS Data retrieved successfully.
* @retval NRF_ERROR_NOT_FOUND The peer ID is invalid or unallocated.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t gccm_remote_db_retrieve(pm_peer_id_t peer_id,
ble_gatt_db_srv_t * p_remote_db,
uint32_t * p_n_services);
/** @}
* @endcond
*/
#endif /* GATTC_CACHE_MANAGER_H__ */

View File

@ -1,396 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "gatts_cache_manager.h"
#include <string.h>
#include "nrf_ble_gap.h"
#include "ble_conn_state.h"
#include "peer_manager_types.h"
#include "peer_manager_internal.h"
#include "peer_database.h"
#include "id_manager.h"
#include "sdk_common.h"
#define SYS_ATTR_SYS (BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS) /**< Shorthand define for the flag for system attributes. */
#define SYS_ATTR_USR (BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS) /**< Shorthand define for the flag for user attributes. */
#define SYS_ATTR_BOTH (SYS_ATTR_SYS | SYS_ATTR_USR) /**< Shorthand define for the combined flags for system and user attributes. */
/**@brief Structure containing the module variable(s) of the GSCM module.
*/
typedef struct
{
gscm_evt_handler_t evt_handler; /**< The event handler to use for outbound GSCM events. */
pm_peer_id_t current_sc_store_peer_id;
} gscm_t;
static gscm_t m_gscm =
{
.current_sc_store_peer_id = PM_PEER_ID_INVALID,
}; /**< Instantiation of module variable(s). */
#define MODULE_INITIALIZED (m_gscm.evt_handler != NULL)
#include "sdk_macros.h"
/**@brief Function for resetting the module variable(s) of the GSCM module.
*
* @param[out] p_gscm The instance to reset.
*/
static void internal_state_reset(gscm_t * p_gscm)
{
memset(p_gscm, 0, sizeof(gscm_t));
p_gscm->current_sc_store_peer_id = PM_PEER_ID_INVALID;
}
//lint -save -e550
/**@brief Function for storing service_changed_pending = true to flash for all peers, in sequence.
*
* This function aborts if it gets @ref NRF_ERROR_BUSY when trying to store. A subsequent call will
* continue where the last call was aborted.
*/
static void service_changed_pending_set(void)
{
VERIFY_MODULE_INITIALIZED_VOID();
static const bool service_changed_pending = true;
ret_code_t err_code;
//lint -save -e65 -e64
pm_peer_data_const_t peer_data =
{
.data_id = PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING,
.length_words = PM_SC_STATE_N_WORDS(),
.p_service_changed_pending = &service_changed_pending,
};
//lint -restore
err_code = pdb_raw_store(m_gscm.current_sc_store_peer_id, &peer_data, NULL);
while((m_gscm.current_sc_store_peer_id != PM_PEER_ID_INVALID) && (err_code != NRF_ERROR_BUSY))
{
m_gscm.current_sc_store_peer_id = pdb_next_peer_id_get(m_gscm.current_sc_store_peer_id);
err_code = pdb_raw_store(m_gscm.current_sc_store_peer_id, &peer_data, NULL);
}
}
//lint -restore
/**@brief Event handler for events from the peer_database module.
*
* @param[in] p_event The event that has happend with peer id and flags.
*/
static void pdb_evt_handler(pdb_evt_t const * p_event)
{
if (p_event->evt_id == PDB_EVT_RAW_STORED)
{
if (p_event->data_id == PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING)
{
ret_code_t err_code;
pm_peer_data_flash_t peer_data;
err_code = pdb_read_buf_get(p_event->peer_id, PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, &peer_data, NULL);
if (err_code == NRF_SUCCESS)
{
gscm_evt_t gscm_evt;
gscm_evt.evt_id = GSCM_EVT_SC_STATE_STORED;
gscm_evt.peer_id = p_event->peer_id;
gscm_evt.params.sc_state_stored.state = &peer_data.p_service_changed_pending;
m_gscm.evt_handler(&gscm_evt);
}
}
}
if (m_gscm.current_sc_store_peer_id != PM_PEER_ID_INVALID)
{
service_changed_pending_set();
}
}
ret_code_t gscm_init(gscm_evt_handler_t evt_handler)
{
ret_code_t err_code;
if (evt_handler == NULL)
{
err_code = NRF_ERROR_NULL;
}
else
{
err_code = pdb_register(pdb_evt_handler);
if (err_code == NRF_SUCCESS)
{
internal_state_reset(&m_gscm);
m_gscm.evt_handler = evt_handler;
}
}
return err_code;
}
ret_code_t gscm_local_db_cache_update(uint16_t conn_handle)
{
VERIFY_MODULE_INITIALIZED();
pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle);
ret_code_t err_code;
if (peer_id == PM_PEER_ID_INVALID)
{
return BLE_ERROR_INVALID_CONN_HANDLE;
}
else
{
pm_peer_data_t peer_data;
uint16_t n_bufs = 1;
bool retry_with_bigger_buffer = false;
do
{
retry_with_bigger_buffer = false;
err_code = pdb_write_buf_get(peer_id, PM_PEER_DATA_ID_GATT_LOCAL, n_bufs++, &peer_data);
if (err_code == NRF_SUCCESS)
{
pm_peer_data_local_gatt_db_t * p_local_gatt_db = peer_data.p_local_gatt_db;
p_local_gatt_db->flags = SYS_ATTR_BOTH;
err_code = sd_ble_gatts_sys_attr_get(conn_handle, &p_local_gatt_db->data[0], &p_local_gatt_db->len, p_local_gatt_db->flags);
if (err_code == NRF_SUCCESS)
{
err_code = pdb_write_buf_store(peer_id, PM_PEER_DATA_ID_GATT_LOCAL);
}
else
{
if (err_code == NRF_ERROR_DATA_SIZE)
{
// The sys attributes are bigger than the requested write buffer.
retry_with_bigger_buffer = true;
}
else if (err_code == NRF_ERROR_NOT_FOUND)
{
// There are no sys attributes in the GATT db, so nothing needs to be stored.
err_code = NRF_SUCCESS;
}
ret_code_t err_code_release = pdb_write_buf_release(peer_id, PM_PEER_DATA_ID_GATT_LOCAL);
if (err_code_release != NRF_SUCCESS)
{
err_code = NRF_ERROR_INTERNAL;
}
}
}
else if (err_code == NRF_ERROR_INVALID_PARAM)
{
// The sys attributes are bigger than the entire write buffer.
err_code = NRF_ERROR_DATA_SIZE;
}
} while (retry_with_bigger_buffer);
}
return err_code;
}
ret_code_t gscm_local_db_cache_apply(uint16_t conn_handle)
{
VERIFY_MODULE_INITIALIZED();
pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle);
ret_code_t err_code;
pm_peer_data_flash_t peer_data;
uint8_t const * p_sys_attr_data = NULL;
uint16_t sys_attr_len = 0;
uint32_t sys_attr_flags = (SYS_ATTR_BOTH);
bool all_attributes_applied = true;
if (peer_id != PM_PEER_ID_INVALID)
{
err_code = pdb_read_buf_get(peer_id, PM_PEER_DATA_ID_GATT_LOCAL, &peer_data, NULL);
if (err_code == NRF_SUCCESS)
{
pm_peer_data_local_gatt_db_t const * p_local_gatt_db;
p_local_gatt_db = peer_data.p_local_gatt_db;
p_sys_attr_data = p_local_gatt_db->data;
sys_attr_len = p_local_gatt_db->len;
sys_attr_flags = p_local_gatt_db->flags;
}
}
do
{
err_code = sd_ble_gatts_sys_attr_set(conn_handle, p_sys_attr_data, sys_attr_len, sys_attr_flags);
if (err_code == NRF_ERROR_NO_MEM)
{
err_code = NRF_ERROR_BUSY;
}
else if (err_code == NRF_ERROR_INVALID_STATE)
{
err_code = NRF_SUCCESS;
}
else if (err_code == NRF_ERROR_INVALID_DATA)
{
all_attributes_applied = false;
if (sys_attr_flags & SYS_ATTR_USR)
{
// Try setting only system attributes.
sys_attr_flags = SYS_ATTR_SYS;
}
else if (p_sys_attr_data || sys_attr_len)
{
// Try reporting that none exist.
p_sys_attr_data = NULL;
sys_attr_len = 0;
sys_attr_flags = SYS_ATTR_BOTH;
}
else
{
err_code = NRF_ERROR_INTERNAL;
}
}
} while (err_code == NRF_ERROR_INVALID_DATA);
if (!all_attributes_applied)
{
err_code = NRF_ERROR_INVALID_DATA;
}
return err_code;
}
ret_code_t gscm_local_db_cache_set(pm_peer_id_t peer_id, pm_peer_data_local_gatt_db_t * p_local_db)
{
VERIFY_MODULE_INITIALIZED();
pm_peer_data_const_t peer_data;
memset(&peer_data, 0, sizeof(pm_peer_data_const_t));
peer_data.data_id = PM_PEER_DATA_ID_GATT_LOCAL;
peer_data.p_local_gatt_db = p_local_db;
return pdb_raw_store(peer_id, &peer_data, NULL);
}
ret_code_t gscm_local_db_cache_get(pm_peer_id_t peer_id, pm_peer_data_local_gatt_db_t * p_local_db)
{
VERIFY_MODULE_INITIALIZED();
pm_peer_data_t peer_data;
memset(&peer_data, 0, sizeof(pm_peer_data_t));
peer_data.p_local_gatt_db = p_local_db;
return pdb_raw_read(peer_id, PM_PEER_DATA_ID_GATT_LOCAL, &peer_data);
}
void gscm_local_database_has_changed(void)
{
VERIFY_MODULE_INITIALIZED_VOID();
m_gscm.current_sc_store_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID);
service_changed_pending_set();
}
bool gscm_service_changed_ind_needed(uint16_t conn_handle)
{
ret_code_t err_code;
pm_peer_data_flash_t peer_data;
pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle);
err_code = pdb_read_buf_get(peer_id, PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING, &peer_data, NULL);
if (err_code != NRF_SUCCESS)
{
return false;
}
return &peer_data.p_service_changed_pending;
}
ret_code_t gscm_service_changed_ind_send(uint16_t conn_handle)
{
static uint16_t start_handle = 0x0000;
const uint16_t end_handle = 0xFFFF;
ret_code_t err_code;
do
{
err_code = sd_ble_gatts_service_changed(conn_handle, start_handle, end_handle);
if (err_code == BLE_ERROR_INVALID_ATTR_HANDLE)
{
start_handle += 1;
}
} while (err_code == BLE_ERROR_INVALID_ATTR_HANDLE);
return err_code;
}
void gscm_db_change_notification_done(pm_peer_id_t peer_id)
{
VERIFY_MODULE_INITIALIZED_VOID();
static const bool service_changed_pending = false;
//lint -save -e65 -e64
pm_peer_data_const_t peer_data =
{
.data_id = PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING,
.length_words = PM_SC_STATE_N_WORDS(),
.p_service_changed_pending = &service_changed_pending,
};
//lint -restore
// Don't need to check return code, because all error conditions can be ignored.
//lint -save -e550
(void) pdb_raw_store(peer_id, &peer_data, NULL);
//lint -restore
}

View File

@ -1,228 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 GATTS_CACHE_MANAGER_H__
#define GATTS_CACHE_MANAGER_H__
#include <stdint.h>
#include "sdk_errors.h"
#include "nrf_ble.h"
#include "nrf_ble_gap.h"
#include "peer_manager_types.h"
/**
* @cond NO_DOXYGEN
* @defgroup gatts_cache_manager GATT Server Cache Manager
* @ingroup peer_manager
* @{
* @brief An internal module of @ref peer_manager. A module for managing persistent storing of GATT
* attributes pertaining to the GATT server role of the local device.
*/
/**@brief Events that can come from the GATT Server Cache Manager module.
*/
typedef enum
{
GSCM_EVT_LOCAL_DB_CACHE_STORED, /**< The persistent cache for the local database has been updated with provided values, for one peer. */
GSCM_EVT_LOCAL_DB_CACHE_UPDATED, /**< The persistent cache for the local database has been updated with values from the SoftDevice, for one peer. */
GSCM_EVT_SC_STATE_STORED, /**< The service changed pending flag in persistent storage has been updated, for one peer. */
} gscm_evt_id_t;
/**@brief Structure containing an event from the GSCM module.
*/
typedef struct
{
gscm_evt_id_t evt_id; /**< The type of event this is. */
pm_peer_id_t peer_id; /**< The peer ID this event pertains to. */
union
{
struct
{
uint16_t conn_handle; /**< The connection this event pertains to. */
} local_db_cache_updated;
struct
{
bool state; /**< The newly stored state of the Service Changed pending flag. */
} sc_state_stored;
} params; /**< Event parameters specific to certain event types. */
} gscm_evt_t;
/**@brief Event handler for events from the GATT Server Cache Manager module.
*
* @param[in] event The event that has happened.
* @param[in] peer The id of the peer the event pertains to.
* @param[in] flags The data the event pertains to.
*/
typedef void (*gscm_evt_handler_t)(gscm_evt_t const * p_event);
/**@brief Function for initializing the GATT Server Cache Manager module.
*
* @param[in] evt_handler Callback for events from the GATT Server Cache Manager module.
*
* @retval NRF_SUCCESS Initialization was successful.
* @retval NRF_ERROR_NULL evt_handler was NULL.
*/
ret_code_t gscm_init(gscm_evt_handler_t evt_handler);
/**@brief Function for triggering local GATT database data to be stored persistently. Values are
* retrieved from the SoftDevice and written to persistent storage.
*
* @param[in] conn_handle Connection handle to perform update on.
*
* @retval NRF_SUCCESS Store operation started.
* @retval BLE_ERROR_INVALID_CONN_HANDLE conn_handle does not refer to an active connection with a
* bonded peer.
* @retval NRF_ERROR_BUSY Unable to perform operation at this time. Reattempt later.
* @retval NRF_ERROR_DATA_SIZE Write buffer not large enough. Call will never work with
* this GATT database.
* @retval NRF_ERROR_NO_MEM No room in persistent_storage. Free up space; the
* operation will be automatically reattempted after the
* next compression procedure
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t gscm_local_db_cache_update(uint16_t conn_handle);
/**@brief Function for applying stored local GATT database data to the SoftDevice. Values are
* retrieved from persistent storage and given to the SoftDevice.
*
* @param[in] conn_handle Connection handle to apply values to.
*
* @retval NRF_SUCCESS Store operation started.
* @retval BLE_ERROR_INVALID_CONN_HANDLE conn_handle does not refer to an active connection with a
* bonded peer.
* @retval NRF_ERROR_INVALID_DATA The stored data was rejected by the SoftDevice, which
* probably means that the local database has changed. The
* system part of the sys_attributes was attempted applied,
* so service changed indications can be sent to subscribers.
* @retval NRF_ERROR_BUSY Unable to perform operation at this time. Reattempt later.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
* @return An unexpected return value from an internal function call.
*/
ret_code_t gscm_local_db_cache_apply(uint16_t conn_handle);
/**@brief Function for setting new values in the local database cache.
*
* @note If the peer is connected, the values will also be applied immediately to the connection.
* @note The data in the pointer must be available until the GSCM_EVT_LOCAL_DB_STORED event is
* received.
*
* @param[in] peer_id Peer to set values for.
* @param[in] p_local_db Database values to apply. If NULL, the values will instead be cleared.
*
* @retval NRF_SUCCESS Operation started, and values were applied (if connected).
* @retval NRF_ERROR_NOT_FOUND The peer ID was invalid or unallocated.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
* @return An unexpected return value from an internal function call.
*/
ret_code_t gscm_local_db_cache_set(pm_peer_id_t peer_id, pm_peer_data_local_gatt_db_t * p_local_db);
/**@brief Function for retrieving values in the local database cache.
*
* @param[in] peer_id Peer to get values for.
* @param[inout] p_local_db Where to store the data. The length field needs to reflect the
* available buffer space. On a successful read, the length field is
* updated to match the length of the read data.
*
* @retval NRF_SUCCESS Values retrieved successfully.
* @retval NRF_ERROR_NOT_FOUND The peer ID was invalid or unallocated.
* @retval NRF_ERROR_NULL p_local_db was NULL.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t gscm_local_db_cache_get(pm_peer_id_t peer_id, pm_peer_data_local_gatt_db_t * p_local_db);
/**@brief Function for storing the fact that the local database has changed, for all currently
* bonded peers.
*
* @note This will cause a later call to @ref gscm_service_changed_ind_needed to return true for
* a connection with a currently bonded peer.
*/
void gscm_local_database_has_changed(void);
/**@brief Function for checking if a service changed indication should be sent.
*
* @param[in] conn_handle The connection to check.
*
* @return true if a service changed indication should be sent, false if not.
*/
bool gscm_service_changed_ind_needed(uint16_t conn_handle);
/**@brief Function for sending a service changed indication to a connected peer.
*
* @param[in] conn_handle The connection to send the indication on.
*
* @retval NRF_SUCCESS Indication sent or not needed.
* @retval BLE_ERROR_INVALID_CONN_HANDLE conn_handle does not refer to an active connection.
* @retval NRF_ERROR_BUSY Unable to send indication at this time. Reattempt later.
* @retval BLE_ERROR_GATTS_SYS_ATTR_MISSING Information missing. Apply local cache, then reattempt.
* @retval NRF_ERROR_INVALID_PARAM From @ref sd_ble_gatts_service_changed. Unexpected.
* @retval NRF_ERROR_NOT_SUPPORTED Service changed characteristic is not present.
* @retval NRF_ERROR_INVALID_STATE Service changed cannot be indicated to this peer
* because the peer has not subscribed to it.
*/
ret_code_t gscm_service_changed_ind_send(uint16_t conn_handle);
/**@brief Function for specifying that a peer has been made aware of the latest local database
* change.
*
* @note After calling this, a later call to @ref gscm_service_changed_ind_needed will to return
* false for this peer unless @ref gscm_local_database_has_changed is called again.
*
* @param[in] peer_id The connection to send the indication on.
*/
void gscm_db_change_notification_done(pm_peer_id_t peer_id);
/** @}
* @endcond
*/
#endif /* GATTS_CACHE_MANAGER_H__ */

View File

@ -1,758 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "id_manager.h"
#include <string.h>
#include "nrf_soc.h"
#include "nrf_ble_gap.h"
#include "ble_conn_state.h"
#include "peer_manager_types.h"
#include "peer_database.h"
#include "nordic_common.h"
#include "sdk_common.h"
#define IM_MAX_CONN_HANDLES 8
#define IM_NO_INVALID_CONN_HANDLES 0xFF
#define MAX_REGISTRANTS 3
#define WHITELIST_MAX_COUNT MAX(BLE_GAP_WHITELIST_ADDR_MAX_COUNT, \
BLE_GAP_WHITELIST_IRK_MAX_COUNT)
#define IM_ADDR_CLEARTEXT_LENGTH 3
#define IM_ADDR_CIPHERTEXT_LENGTH 3
typedef struct
{
pm_peer_id_t peer_id;
uint16_t conn_handle;
ble_gap_addr_t peer_address;
} im_connection_t;
typedef struct
{
im_evt_handler_t evt_handlers[MAX_REGISTRANTS];
uint8_t n_registrants;
im_connection_t connections[8];
pm_peer_id_t irk_whitelist_peer_ids[BLE_GAP_WHITELIST_IRK_MAX_COUNT];
ble_gap_irk_t whitelist_irks[BLE_GAP_WHITELIST_IRK_MAX_COUNT];
ble_gap_addr_t whitelist_addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT];
uint8_t n_irk_whitelist_peer_ids;
ble_conn_state_user_flag_id_t conn_state_user_flag_id;
} im_t;
static im_t m_im = {.n_registrants = 0};
#define MODULE_INITIALIZED (m_im.n_registrants > 0)
#include "sdk_macros.h"
static void internal_state_reset()
{
memset(&m_im, 0, sizeof(im_t));
m_im.n_registrants = 0;
m_im.n_irk_whitelist_peer_ids = 0;
m_im.conn_state_user_flag_id = BLE_CONN_STATE_USER_FLAG_INVALID;
for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++)
{
m_im.connections[i].conn_handle = BLE_CONN_HANDLE_INVALID;
}
}
/**@brief Function for sending an event to all registered event handlers.
*
* @param[in] p_event The event to distribute.
*/
static void evt_send(im_evt_t * p_event)
{
for (uint32_t i = 0; i < m_im.n_registrants; i++)
{
m_im.evt_handlers[i](p_event);
}
}
/**@brief Function finding a free position in m_im.connections.
*
* @detail All connection handles in the m_im.connections array are checked against the connection
* state module. The index of the first one that is not a connection handle for a current
* connection is returned. This position in the array can safely be used for a new connection.
*
* @return Either the index of a free position in the array or IM_NO_INVALID_CONN_HANDLES if no free
position exists.
*/
uint8_t get_free_connection()
{
for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++)
{
// Query the connection state module to check if the connection handle does not belong to a
// valid connection.
if (!ble_conn_state_user_flag_get(m_im.connections[i].conn_handle, m_im.conn_state_user_flag_id))
{
return i;
}
}
// If all connection handles belong to a valid connection, return IM_NO_INVALID_CONN_HANDLES.
return IM_NO_INVALID_CONN_HANDLES;
}
/**@brief Function finding a particular connection handle m_im.connections.
*
* @param[in] conn_handle The handle to find.
*
* @return Either the index of the conn_handle in the array or IM_NO_INVALID_CONN_HANDLES if the
* handle was not found.
*/
uint8_t get_connection_by_conn_handle(uint16_t conn_handle)
{
if (ble_conn_state_user_flag_get(conn_handle, m_im.conn_state_user_flag_id))
{
for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++)
{
if (m_im.connections[i].conn_handle == conn_handle)
{
return i;
}
}
}
// If all connection handles belong to a valid connection, return IM_NO_INVALID_CONN_HANDLES.
return IM_NO_INVALID_CONN_HANDLES;
}
/**@brief Function for registering a new connection instance.
*
* @param[in] conn_handle The handle of the new connection.
* @param[in] p_ble_addr The address used to connect.
*
* @return Either the index of the new connection in the array or IM_NO_INVALID_CONN_HANDLES if no
* free position exists.
*/
uint8_t new_connection(uint16_t conn_handle, ble_gap_addr_t * p_ble_addr)
{
uint8_t conn_index = IM_NO_INVALID_CONN_HANDLES;
if ((p_ble_addr != NULL) && (conn_handle != BLE_CONN_HANDLE_INVALID))
{
ble_conn_state_user_flag_set(conn_handle, m_im.conn_state_user_flag_id, true);
conn_index = get_connection_by_conn_handle(conn_handle);
if (conn_index == IM_NO_INVALID_CONN_HANDLES)
{
conn_index = get_free_connection();
}
if (conn_index != IM_NO_INVALID_CONN_HANDLES)
{
m_im.connections[conn_index].conn_handle = conn_handle;
m_im.connections[conn_index].peer_id = PM_PEER_ID_INVALID;
m_im.connections[conn_index].peer_address = *p_ble_addr;
}
}
return conn_index;
}
/**@brief Function checking the validity of an IRK
*
* @detail An all-zero IRK is not valid. This function will check if a given IRK is valid.
*
* @param[in] irk The IRK for which the validity is going to be checked.
*
* @retval true The IRK is valid.
* @retval false The IRK is invalid.
*/
bool is_valid_irk(ble_gap_irk_t const * irk)
{
for (uint32_t i = 0; i < BLE_GAP_SEC_KEY_LEN; i++)
{
if (irk->irk[i] != 0)
{
return true;
}
}
return false;
}
/**@brief Function for comparing two addresses to determine if they are identical
*
* @note The address type need to be identical, as well as every bit in the address itself.
*
* @param[in] p_addr1 The first address to be compared.
* @param[in] p_addr2 The second address to be compared.
*
* @retval true The addresses are identical.
* @retval false The addresses are not identical.
*/
bool addr_compare(ble_gap_addr_t const * p_addr1, ble_gap_addr_t const * p_addr2)
{
if ((p_addr1 == NULL) || (p_addr2 == NULL))
{
return false;
}
// Check that the addr type is identical, return false if it is not
if (p_addr1->addr_type != p_addr2->addr_type)
{
return false;
}
// Check if the addr bytes are is identical
return (memcmp(p_addr1->addr, p_addr2->addr, BLE_GAP_ADDR_LEN) == 0);
}
void im_ble_evt_handler(ble_evt_t * ble_evt)
{
ret_code_t err_code;
switch (ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:
{
pm_peer_id_t bonded_matching_peer_id = PM_PEER_ID_INVALID;
if (ble_evt->evt.gap_evt.params.connected.irk_match == 1)
{
// The peer was matched using a whitelist.
bonded_matching_peer_id
= m_im.irk_whitelist_peer_ids[ble_evt->evt.gap_evt.params.connected.irk_match_idx];
}
else if ( ble_evt->evt.gap_evt.params.connected.peer_addr.addr_type
!= BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE)
{
/* Search the database for bonding data matching the one that triggered the event.
* Public and static addresses can be matched on address alone, while resolvable
* random addresses can be resolved agains known IRKs. Non-resolvable random addresses
* are never matching because they are not longterm form of identification.
*/
pm_peer_id_t compared_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID);
while ( (compared_peer_id != PM_PEER_ID_INVALID)
&& (bonded_matching_peer_id == PM_PEER_ID_INVALID))
{
pm_peer_data_flash_t compared_data;
switch (ble_evt->evt.gap_evt.params.connected.peer_addr.addr_type)
{
case BLE_GAP_ADDR_TYPE_PUBLIC:
/* fall-through */
case BLE_GAP_ADDR_TYPE_RANDOM_STATIC:
err_code = pdb_read_buf_get(compared_peer_id,
PM_PEER_DATA_ID_BONDING,
&compared_data,
NULL);
if ((err_code == NRF_SUCCESS) &&
addr_compare(&ble_evt->evt.gap_evt.params.connected.peer_addr,
&compared_data.p_bonding_data->peer_id.id_addr_info)
)
{
bonded_matching_peer_id = compared_peer_id;
}
break;
case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE:
err_code = pdb_read_buf_get(compared_peer_id,
PM_PEER_DATA_ID_BONDING,
&compared_data,
NULL);
if (err_code == NRF_SUCCESS &&
im_address_resolve(&ble_evt->evt.gap_evt.params.connected.peer_addr,
&compared_data.p_bonding_data->peer_id.id_info)
)
{
bonded_matching_peer_id = compared_peer_id;
}
break;
case BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE:
// Should not happen.
break;
default:
break;
}
compared_peer_id = pdb_next_peer_id_get(compared_peer_id);
}
}
uint8_t new_index = new_connection(ble_evt->evt.gap_evt.conn_handle, &ble_evt->evt.gap_evt.params.connected.peer_addr);
UNUSED_VARIABLE(new_index);
if (bonded_matching_peer_id != PM_PEER_ID_INVALID)
{
im_new_peer_id(ble_evt->evt.gap_evt.conn_handle, bonded_matching_peer_id);
// Send a bonded peer event
im_evt_t im_evt;
im_evt.conn_handle = ble_evt->evt.gap_evt.conn_handle;
im_evt.evt_id = IM_EVT_BONDED_PEER_CONNECTED;
evt_send(&im_evt);
}
}
}
}
/**@brief Function to compare two sets of bonding data to check if they belong to the same device.
* @note Invalid irks will never match even though they are identical.
*
* @param[in] p_bonding_data1 First bonding data for comparison
* @param[in] p_bonding_data2 Second bonding data for comparison
*
* @return True if the input matches, false if it does not.
*/
bool is_duplicate_bonding_data(pm_peer_data_bonding_t const * p_bonding_data1,
pm_peer_data_bonding_t const * p_bonding_data2)
{
bool valid_irk = is_valid_irk(&p_bonding_data1->peer_id.id_info);
bool duplicate_irk = valid_irk &&
(memcmp(p_bonding_data1->peer_id.id_info.irk,
p_bonding_data2->peer_id.id_info.irk,
BLE_GAP_SEC_KEY_LEN) == 0
);
bool duplicate_addr = addr_compare(&p_bonding_data1->peer_id.id_addr_info,
&p_bonding_data2->peer_id.id_addr_info
);
return duplicate_irk || duplicate_addr;
}
/**@brief Event handler for events from the peer_database module.
*
* @param[in] p_event The event that has happend with peer id and flags.
*/
static void pdb_evt_handler(pdb_evt_t const * p_event)
{
ret_code_t err_code;
if ((p_event != NULL) && (p_event->evt_id == PDB_EVT_WRITE_BUF_STORED))
{
// If new data about peer id has been stored it is compared to other peers peer ids in
// search of duplicates.
if (p_event->data_id == PM_PEER_DATA_ID_BONDING)
{
pm_peer_data_flash_t written_data;
err_code = pdb_read_buf_get(p_event->peer_id, PM_PEER_DATA_ID_BONDING, &written_data, NULL);
if (err_code == NRF_SUCCESS)
{
pm_peer_id_t compared_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID);
while (compared_peer_id != PM_PEER_ID_INVALID)
{
pm_peer_data_flash_t compared_data;
err_code = pdb_read_buf_get(compared_peer_id,
PM_PEER_DATA_ID_BONDING,
&compared_data,
NULL);
if ( err_code == NRF_SUCCESS &&
p_event->peer_id != compared_peer_id &&
is_duplicate_bonding_data(written_data.p_bonding_data,
compared_data.p_bonding_data)
)
{
im_evt_t im_evt;
im_evt.conn_handle = im_conn_handle_get(p_event->peer_id);
im_evt.evt_id = IM_EVT_DUPLICATE_ID;
im_evt.params.duplicate_id.peer_id_1 = p_event->peer_id;
im_evt.params.duplicate_id.peer_id_2 = compared_peer_id;
evt_send(&im_evt);
}
compared_peer_id = pdb_next_peer_id_get(compared_peer_id);
}
}
}
}
}
ret_code_t im_register(im_evt_handler_t evt_handler)
{
VERIFY_PARAM_NOT_NULL(evt_handler);
ret_code_t err_code = NRF_SUCCESS;
if (!MODULE_INITIALIZED)
{
internal_state_reset();
m_im.conn_state_user_flag_id = ble_conn_state_user_flag_acquire();
if (m_im.conn_state_user_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID)
{
err_code = NRF_ERROR_NO_MEM;
}
else
{
err_code = pdb_register(pdb_evt_handler);
}
}
if (err_code == NRF_SUCCESS)
{
if ((m_im.n_registrants < MAX_REGISTRANTS))
{
m_im.evt_handlers[m_im.n_registrants++] = evt_handler;
}
else
{
err_code = NRF_ERROR_NO_MEM;
}
}
return err_code;
}
pm_peer_id_t im_peer_id_get_by_conn_handle(uint16_t conn_handle)
{
uint8_t conn_index = get_connection_by_conn_handle(conn_handle);
if (MODULE_INITIALIZED && (conn_index != IM_NO_INVALID_CONN_HANDLES))
{
return m_im.connections[conn_index].peer_id;
}
return PM_PEER_ID_INVALID;
}
ret_code_t im_ble_addr_get(uint16_t conn_handle, ble_gap_addr_t * p_ble_addr)
{
VERIFY_MODULE_INITIALIZED();
VERIFY_PARAM_NOT_NULL(p_ble_addr);
uint8_t conn_index = get_connection_by_conn_handle(conn_handle);
if (conn_index != IM_NO_INVALID_CONN_HANDLES)
{
*p_ble_addr = m_im.connections[conn_index].peer_address;
return NRF_SUCCESS;
}
return NRF_ERROR_NOT_FOUND;
}
bool im_master_ids_compare(ble_gap_master_id_t const * p_master_id1,
ble_gap_master_id_t const * p_master_id2)
{
if(!im_master_id_is_valid(p_master_id1))
{
return false;
}
if (p_master_id1->ediv != p_master_id2->ediv)
{
return false;
}
return (memcmp(p_master_id1->rand, p_master_id2->rand, BLE_GAP_SEC_RAND_LEN) == 0);
}
pm_peer_id_t im_peer_id_get_by_master_id(ble_gap_master_id_t * p_master_id)
{
ret_code_t err_code;
// For each stored peer, check if the master_id match p_master_id
pm_peer_id_t compared_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID);
while (compared_peer_id != PM_PEER_ID_INVALID)
{
pm_peer_data_flash_t compared_data;
ble_gap_master_id_t const * p_compared_master_id;
err_code = pdb_read_buf_get(compared_peer_id, PM_PEER_DATA_ID_BONDING, &compared_data, NULL);
if (err_code == NRF_SUCCESS)
{
p_compared_master_id = &compared_data.p_bonding_data->own_ltk.master_id;
if (im_master_ids_compare(p_master_id, p_compared_master_id))
{
// If a matching master_id is found return the peer_id
return compared_peer_id;
}
p_compared_master_id = &compared_data.p_bonding_data->peer_ltk.master_id;
if (im_master_ids_compare(p_master_id, p_compared_master_id))
{
// If a matching master_id is found return the peer_id
return compared_peer_id;
}
}
compared_peer_id = pdb_next_peer_id_get(compared_peer_id);
}
// If no matching master_id is found return the PM_PEER_ID_INVALID
return PM_PEER_ID_INVALID;
}
pm_peer_id_t im_peer_id_get_by_irk_match_idx(uint8_t irk_match_idx)
{
// Verify that the requested idx is within the list
if (irk_match_idx < m_im.n_irk_whitelist_peer_ids)
{
// Return the peer_id from the white list
return m_im.irk_whitelist_peer_ids[irk_match_idx];
}
else
{
// Return PM_PEER_ID_INVALID to indicate that there was no peer with the requested idx
return PM_PEER_ID_INVALID;
}
}
uint16_t im_conn_handle_get(pm_peer_id_t peer_id)
{
for (uint32_t i = 0; i < IM_MAX_CONN_HANDLES; i++)
{
if (peer_id == m_im.connections[i].peer_id)
{
return m_im.connections[i].conn_handle;
}
}
return BLE_CONN_HANDLE_INVALID;
}
bool im_master_id_is_valid(ble_gap_master_id_t const * p_master_id)
{
if (p_master_id->ediv != 0)
{
return true;
}
for (uint32_t i = 0; i < BLE_GAP_SEC_RAND_LEN; i++)
{
if (p_master_id->rand[i] != 0)
{
return true;
}
}
return false;
}
/**@brief Function to set the peer ID associated with a connection handle.
*
* @param[in] conn_handle The connection handle.
* @param[in] peer_id The peer ID to associate with @c conn_handle.
*/
static void peer_id_set(uint16_t conn_handle, pm_peer_id_t peer_id)
{
uint8_t conn_index = get_connection_by_conn_handle(conn_handle);
if (conn_index != IM_NO_INVALID_CONN_HANDLES)
{
m_im.connections[conn_index].peer_id = peer_id;
}
}
void im_new_peer_id(uint16_t conn_handle, pm_peer_id_t peer_id)
{
peer_id_set(conn_handle, peer_id);
}
ret_code_t im_peer_free(pm_peer_id_t peer_id)
{
VERIFY_MODULE_INITIALIZED();
uint16_t conn_handle = im_conn_handle_get(peer_id);
ret_code_t err_code = pdb_peer_free(peer_id);
if ((conn_handle != BLE_CONN_HANDLE_INVALID) && (err_code == NRF_SUCCESS))
{
peer_id_set(conn_handle, PM_PEER_ID_INVALID);
}
return err_code;
}
ret_code_t im_whitelist_create(pm_peer_id_t * p_peer_ids,
uint8_t n_peer_ids,
ble_gap_whitelist_t * p_whitelist)
{
VERIFY_MODULE_INITIALIZED();
VERIFY_PARAM_NOT_NULL(p_whitelist);
ret_code_t err_code;
p_whitelist->addr_count = 0;
p_whitelist->irk_count = 0;
m_im.n_irk_whitelist_peer_ids = 0;
for (uint32_t peer_index = 0; peer_index < n_peer_ids; peer_index++)
{
uint16_t conn_handle = im_conn_handle_get(p_peer_ids[peer_index]);
if (ble_conn_state_status(conn_handle) != BLE_CONN_STATUS_CONNECTED)
{
pm_peer_data_flash_t peer_data;
err_code = pdb_read_buf_get(p_peer_ids[peer_index], PM_PEER_DATA_ID_BONDING, &peer_data, NULL);
if (err_code == NRF_ERROR_INVALID_PARAM || err_code == NRF_ERROR_NOT_FOUND)
{
return NRF_ERROR_INVALID_PARAM;
}
if (p_whitelist->pp_addrs != NULL &&
peer_data.p_bonding_data->peer_id.id_addr_info.addr_type
!= BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE &&
peer_data.p_bonding_data->peer_id.id_addr_info.addr_type
!= BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE
)
{
memcpy(m_im.whitelist_addrs[peer_index].addr,
peer_data.p_bonding_data->peer_id.id_addr_info.addr,
BLE_GAP_ADDR_LEN
);
m_im.whitelist_addrs[peer_index].addr_type =
peer_data.p_bonding_data->peer_id.id_addr_info.addr_type;
p_whitelist->pp_addrs[peer_index] = &m_im.whitelist_addrs[peer_index];
p_whitelist->addr_count++;
}
if (p_whitelist->pp_irks != NULL &&
is_valid_irk(&(peer_data.p_bonding_data->peer_id.id_info))
)
{
memcpy(m_im.whitelist_irks[peer_index].irk,
peer_data.p_bonding_data->peer_id.id_info.irk,
BLE_GAP_SEC_KEY_LEN
);
p_whitelist->pp_irks[peer_index] = &m_im.whitelist_irks[peer_index];
p_whitelist->irk_count++;
m_im.irk_whitelist_peer_ids[peer_index] = p_peer_ids[peer_index];
m_im.n_irk_whitelist_peer_ids++;
}
}
}
return NRF_SUCCESS;
}
ret_code_t im_whitelist_custom(ble_gap_whitelist_t const * p_whitelist)
{
ret_code_t err_code;
pm_peer_id_t new_irk_whitelist_peer_ids[BLE_GAP_WHITELIST_IRK_MAX_COUNT];
uint32_t n_new_irk_whitelist_peer_ids = 0;
VERIFY_PARAM_NOT_NULL(p_whitelist);
for (uint32_t i = 0; i < BLE_GAP_WHITELIST_IRK_MAX_COUNT; i++)
{
new_irk_whitelist_peer_ids[i] = PM_PEER_ID_INVALID;
}
pm_peer_id_t compared_peer_id = pdb_next_peer_id_get(PM_PEER_ID_INVALID);
while (compared_peer_id != PM_PEER_ID_INVALID)
{
pm_peer_data_flash_t compared_data;
err_code = pdb_read_buf_get(compared_peer_id, PM_PEER_DATA_ID_BONDING, &compared_data, NULL);
if (err_code == NRF_SUCCESS)
{
for (uint32_t i = 0; i < p_whitelist->irk_count; i++)
{
bool valid_irk = is_valid_irk(&compared_data.p_bonding_data->peer_id.id_info);
bool duplicate_irk = valid_irk &&
(memcmp(p_whitelist->pp_irks[i]->irk,
compared_data.p_bonding_data->peer_id.id_info.irk,
BLE_GAP_SEC_KEY_LEN) == 0
);
if (duplicate_irk)
{
new_irk_whitelist_peer_ids[i] = compared_peer_id;
n_new_irk_whitelist_peer_ids++;
}
}
}
compared_peer_id = pdb_next_peer_id_get(compared_peer_id);
}
if (n_new_irk_whitelist_peer_ids != p_whitelist->irk_count)
{
return NRF_ERROR_NOT_FOUND;
}
else
{
for (uint32_t i = 0; i < n_new_irk_whitelist_peer_ids; i++)
{
m_im.irk_whitelist_peer_ids[i] = new_irk_whitelist_peer_ids[i];
}
m_im.n_irk_whitelist_peer_ids = n_new_irk_whitelist_peer_ids;
return NRF_SUCCESS;
}
}
/**@brief Function for calculating the ah() hash function described in Bluetooth core specification
* 4.2 section 3.H.2.2.2.
*
* @detail BLE uses a hash function to calculate the first half of a resolvable address
* from the second half of the address and an irk. This function will use the ECB
* periferal to hash these data acording to the Bluetooth core specification.
*
* @note The ECB expect little endian input and output.
* This function expect big endian and will reverse the data as necessary.
*
* @param[in] p_k The key used in the hash function.
* For address resolution this is should be the irk.
* The array must have a length of 16.
* @param[in] p_r The rand used in the hash function. For generating a new address
* this would be a random number. For resolving a resolvable address
* this would be the last half of the address being resolved.
* The array must have a length of 3.
* @param[out] p_local_hash The result of the hash operation. For address resolution this
* will match the first half of the address being resolved if and only
* if the irk used in the hash function is the same one used to generate
* the address.
* The array must have a length of 16.
*/
void ah(uint8_t const * p_k, uint8_t const * p_r, uint8_t * p_local_hash)
{
ret_code_t err_code;
nrf_ecb_hal_data_t ecb_hal_data;
for (uint32_t i = 0; i < SOC_ECB_KEY_LENGTH; i++)
{
ecb_hal_data.key[i] = p_k[SOC_ECB_KEY_LENGTH - 1 - i];
}
memset(ecb_hal_data.cleartext, 0, SOC_ECB_KEY_LENGTH - IM_ADDR_CLEARTEXT_LENGTH);
for (uint32_t i = 0; i < IM_ADDR_CLEARTEXT_LENGTH; i++)
{
ecb_hal_data.cleartext[SOC_ECB_KEY_LENGTH - 1 - i] = p_r[i];
}
err_code = sd_ecb_block_encrypt(&ecb_hal_data); // Can only return NRF_SUCCESS.
UNUSED_VARIABLE(err_code);
for (uint32_t i = 0; i < IM_ADDR_CIPHERTEXT_LENGTH; i++)
{
p_local_hash[i] = ecb_hal_data.ciphertext[SOC_ECB_KEY_LENGTH - 1 - i];
}
}
bool im_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk)
{
if (p_addr->addr_type != BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE)
{
return false;
}
uint8_t hash[IM_ADDR_CIPHERTEXT_LENGTH];
uint8_t local_hash[IM_ADDR_CIPHERTEXT_LENGTH];
uint8_t prand[IM_ADDR_CLEARTEXT_LENGTH];
memcpy(hash, p_addr->addr, IM_ADDR_CIPHERTEXT_LENGTH);
memcpy(prand, &p_addr->addr[IM_ADDR_CIPHERTEXT_LENGTH], IM_ADDR_CLEARTEXT_LENGTH);
ah(p_irk->irk, prand, local_hash);
return (memcmp(hash, local_hash, IM_ADDR_CIPHERTEXT_LENGTH) == 0);
}

View File

@ -1,301 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 PEER_ID_MANAGER_H__
#define PEER_ID_MANAGER_H__
#include <stdint.h>
#include "sdk_errors.h"
#include "nrf_ble.h"
#include "nrf_ble_gap.h"
#include "peer_manager_types.h"
/**
* @cond NO_DOXYGEN
* @defgroup id_manager ID Manager
* @ingroup peer_manager
* @{
* @brief An internal module of @ref peer_manager. A module for keeping track of peer identities
* (IRK and peer address).
*/
/**@brief Events that can come from the ID Manager module.
*/
typedef enum
{
IM_EVT_DUPLICATE_ID, /**< The ID Manager module has detected that two stored peers represent the same peer. */
IM_EVT_BONDED_PEER_CONNECTED, /**< A connected peer has been identified as one of the bonded peers. This can happen immediately on connection, or at a later time. */
} im_evt_id_t;
typedef struct
{
im_evt_id_t evt_id;
uint16_t conn_handle;
union
{
struct
{
pm_peer_id_t peer_id_1;
pm_peer_id_t peer_id_2;
} duplicate_id;
} params;
} im_evt_t;
/**@brief Event handler for events from the ID Manager module.
*
* @param[in] p_event The event that has happened.
*/
typedef void (*im_evt_handler_t)(im_evt_t const * p_event);
/**@brief Function for registering for events from the ID Manager module.
*
* @note This will also initialize the module if needed.
*
* @param[in] evt_handler Callback for events from the ID Manager module.
*
* @retval NRF_SUCCESS Registration was successful.
* @retval NRF_ERROR_NO_MEM No more registrations possible.
* @retval NRF_ERROR_NULL evt_handler was NULL.
*/
ret_code_t im_register(im_evt_handler_t evt_handler);
/**@brief Function for dispatching SoftDevice events to the ID Manager module.
*
* @param[in] p_ble_evt The SoftDevice event.
*/
void im_ble_evt_handler(ble_evt_t * p_ble_evt);
/**@brief Function for getting the corresponding peer ID from a connection handle.
*
* @param[in] conn_handle The connection handle.
*
* @return The corresponding peer ID, or @ref PM_PEER_ID_INVALID if none could be resolved.
*/
pm_peer_id_t im_peer_id_get_by_conn_handle(uint16_t conn_handle);
/**@brief Function for getting the corresponding peer ID from a master ID (EDIV and rand).
*
* @param[in] p_master_id The master ID.
*
* @return The corresponding peer ID, or @ref PM_PEER_ID_INVALID if none could be resolved.
*/
pm_peer_id_t im_peer_id_get_by_master_id(ble_gap_master_id_t * p_master_id);
/**@brief Function for getting the corresponding peer ID from an IRK match index, see @ref
* ble_gap_evt_connected_t.
*
* @param[in] irk_match_idx The IRK match index.
*
* @return The corresponding peer ID, or @ref PM_PEER_ID_INVALID if none could be resolved.
*/
pm_peer_id_t im_peer_id_get_by_irk_match_idx(uint8_t irk_match_idx);
/**@brief Function for getting the corresponding connection handle from a peer ID.
*
* @param[in] peer_id The peer ID.
*
* @return The corresponding connection handle, or @ref BLE_CONN_HANDLE_INVALID if none could be
* resolved.
*/
uint16_t im_conn_handle_get(pm_peer_id_t peer_id);
/**@brief Function for comparing two master ids
* @note Two invalid master IDs will not match.
*
* @param[in] p_master_id1 First master id for comparison
* @param[in] p_master_id2 Second master id for comparison
*
* @return True if the input matches, false if it does not.
*/
bool im_master_ids_compare(ble_gap_master_id_t const * p_master_id1,
ble_gap_master_id_t const * p_master_id2);
/**@brief Function for getting the BLE address used by the peer when connecting.
*
* @param[in] conn_handle The connection handle.
* @param[out] p_ble_addr The BLE address used by the peer when the connection specified by
* conn_handle was established.
*
* @retval NRF_SUCCESS The address was found and copied.
* @retval NRF_ERROR_INVALID_STATE Module not initialized.
* @retval BLE_ERROR_CONN_HANDLE_INVALID conn_handle does not refer to an active connection.
* @retval NRF_ERROR_NULL p_ble_addr was NULL.
*/
ret_code_t im_ble_addr_get(uint16_t conn_handle, ble_gap_addr_t * p_ble_addr);
/**@brief Function for checking whether a master ID is valid or invalid
*
* @param[in] p_master_id The master ID.
*
* @retval true The master id is valid.
* @retval true The master id is invalid (i.e. all zeros).
*/
bool im_master_id_is_valid(ble_gap_master_id_t const * p_master_id);
/**@brief Function for reporting that a new peer ID has been allocated for a specified connection.
*
* @param[in] conn_handle The connection.
* @param[in] peer_id The new peer ID.
*/
void im_new_peer_id(uint16_t conn_handle, pm_peer_id_t peer_id);
/**@brief Function for deleting all of a peer's data from flash and disassociating it from any
* connection handles it is associated with.
*
* @param[in] peer_id The peer to free.
*
* @return Any error code returned by @ref pdb_peer_free.
*/
ret_code_t im_peer_free(pm_peer_id_t peer_id);
/**@brief Function for informing this module of what whitelist will be used.
*
* @details This function is meant to be used when the app wants to use a custom whitelist.
* When using peer manager, this function must be used if a custom whitelist is used.
* Only whitelisted IRKs are of any importance for this function.
*
* @note When using a whitelist, always use the whitelist created/set by the most recent
* call to @ref im_whitelist_create or to this function, whichever happened most recently.
* @note Do not call this function while scanning with another whitelist.
* @note Do not add any irks to the whitelist that are not present in the bonding data of a peer in
* the peer database.
* @note The whitelist is not altered in any way by calling this function. Only the internal state
* of the module is changed.
*
* @param[in] p_whitelist The whitelist.
*
* @retval NRF_SUCCESS Whitelist successfully set.
* @retval NRF_ERROR_NULL p_whitelist was NULL.
* @retval NRF_ERROR_NOT_FOUND One or more of the whitelists irks was not found in the peer_database.
*/
ret_code_t im_whitelist_custom(ble_gap_whitelist_t const * p_whitelist);
/**
* @brief Function for constructing a whitelist for use when advertising.
*
* @note When advertising with whitelist, always use the whitelist created/set by the most recent
* call to this function or to @ref im_whitelist_custom, whichever happened most recently.
* @note Do not call this function while advertising with another whitelist.
*
* @param[in] p_peer_ids The ids of the peers to be added to the whitelist.
* @param[in] n_peer_ids The number of peer ids in p_peer_ids.
* @param[in,out] p_whitelist The constructed whitelist. Note that p_adv_whitelist->pp_addrs
* must be NULL or point to an array with size @ref
* BLE_GAP_WHITELIST_ADDR_MAX_COUNT and p_adv_whitelist->pp_irks
* must be NULL or point to an array with size @ref
* BLE_GAP_WHITELIST_IRK_MAX_COUNT.
*
* @retval NRF_SUCCESS Whitelist successfully created.
* @retval NRF_ERROR_NULL p_whitelist was NULL.
*/
ret_code_t im_whitelist_create(pm_peer_id_t * p_peer_ids,
uint8_t n_peer_ids,
ble_gap_whitelist_t * p_whitelist);
/**
* @brief Function for resolving a resolvable address with an identity resolution key (IRK).
*
* @details This function will use the ECB peripheral to resolve a resolvable address.
* This can be used to resolve the identity of a device distributing a random
* resolvable address based on any IRKs you have received earlier. If an address is
* resolved by an IRK, the device disributing the address must also know the IRK.
*
* @param[in] p_addr A random resolvable address.
* @param[in] p_irk An identity resolution key (IRK).
*
* @retval true The irk used matched the one used to create the address.
* @retval false The irk used did not match the one used to create the address, or an argument was
* NULL.
*/
bool im_address_resolve(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk);
/**@brief Function for calculating the ah() hash function described in Bluetooth core specification
* 4.2 section 3.H.2.2.2.
*
* @detail BLE uses a hash function to calculate the first half of a resolvable address
* from the second half of the address and an irk. This function will use the ECB
* periferal to hash these data acording to the Bluetooth core specification.
*
* @note The ECB expect little endian input and output.
* This function expect big endian and will reverse the data as necessary.
*
* @param[in] p_k The key used in the hash function.
* For address resolution this is should be the irk.
* The array must have a length of 16.
* @param[in] p_r The rand used in the hash function. For generating a new address
* this would be a random number. For resolving a resolvable address
* this would be the last half of the address being resolved.
* The array must have a length of 3.
* @param[out] p_local_hash The result of the hash operation. For address resolution this
* will match the first half of the address being resolved if and only
* if the irk used in the hash function is the same one used to generate
* the address.
* The array must have a length of 16.
*
* @note ====IMPORTANT====
* This is a special modification to the original nRF5x SDK required by the mbed BLE API
* to be able to generate BLE private resolvable addresses. This function is used by
* the BLE API implementation for nRF5xSecurityManager::getAddressFromBondTable() in the
* ble-nrf52832 yotta module.
* =================
*/
void ah(uint8_t const * p_k, uint8_t const * p_r, uint8_t * p_local_hash);
/** @}
* @endcond
*/
#endif /* PEER_ID_MANAGER_H__ */

View File

@ -1,92 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "peer_data.h"
#include "peer_manager_types.h"
#include "fds.h"
#include "sdk_common.h"
void peer_data_parts_get(pm_peer_data_const_t const * p_peer_data, fds_record_chunk_t * p_chunks, uint16_t * p_n_chunks)
{
if (p_n_chunks == NULL)
{
}
else if ((p_peer_data == NULL) || (p_chunks == NULL))
{
*p_n_chunks = 0;
}
else
{
p_chunks[0].p_data = p_peer_data->p_all_data;
p_chunks[0].length_words = p_peer_data->length_words;
*p_n_chunks = 1;
}
}
ret_code_t peer_data_deserialize(pm_peer_data_flash_t const * p_in_data, pm_peer_data_t * p_out_data)
{
ret_code_t err_code = NRF_SUCCESS;
if ((p_in_data == NULL) || (p_out_data == NULL))
{
err_code = NRF_ERROR_NULL;
}
else
{
if (p_out_data->length_words < p_in_data->length_words)
{
p_out_data->length_words = p_in_data->length_words;
err_code = NRF_ERROR_NO_MEM;
}
else
{
p_out_data->length_words = p_in_data->length_words;
p_out_data->data_id = p_in_data->data_id;
memcpy(p_out_data->p_all_data, p_in_data->p_all_data, p_in_data->length_words * 4);
}
}
return err_code;
}

View File

@ -1,84 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 PEER_DATA_H__
#define PEER_DATA_H__
#include <stdint.h>
#include "peer_manager_types.h"
#include "peer_manager_internal.h"
#include "fds.h"
/**
* @cond NO_DOXYGEN
* @defgroup peer_data Peer Data
* @ingroup peer_manager
* @{
* @brief An internal module of @ref peer_manager. This module defines the structure of the data
* that is managed by the @ref peer_manager. It also provides functions for parsing the data.
*/
/**@brief Function for enumerating the separate (non-contiguous) parts of the peer data.
*
* @param[in] p_peer_data The peer data to enumerate.
* @param[out] p_chunks The resulting chunks. This must be an array of at least 2 elements.
* @param[out] p_n_chunks The number of chunks. If this is 0, something went wrong.
*/
void peer_data_parts_get(pm_peer_data_const_t const * p_peer_data, fds_record_chunk_t * p_chunks, uint16_t * p_n_chunks);
/**@brief Function for converting @ref pm_peer_data_flash_t into @ref pm_peer_data_t.
*
* @param[in] p_in_data The source data.
* @param[out] p_out_data The target data structure.
*
* @retval NRF_SUCCESS Successful conversion.
* @retval NRF_ERROR_NULL A parameter was NULL.
* @retval NRF_ERROR_NO_MEM A buffer was not large enough.
*/
ret_code_t peer_data_deserialize(pm_peer_data_flash_t const * p_in_data, pm_peer_data_t * p_out_data);
/** @}
* @endcond
*/
#endif /* PEER_DATA_H__ */

View File

@ -1,787 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "peer_data_storage.h"
#include <stdint.h>
#include <string.h>
#include "sdk_errors.h"
#include "peer_manager_types.h"
#include "peer_manager_internal.h"
#include "peer_id.h"
#include "peer_data.h"
#include "fds.h"
#include "sdk_common.h"
// The number of user that can register with the module.
#define MAX_REGISTRANTS 6
// Macro for verifying that param is not zero.
#define VERIFY_PARAM_NOT_ZERO(param) \
do \
{ \
if (param == 0) \
{ \
return NRF_ERROR_NULL; \
} \
} while(0)
// Macro for verifying that the peer id is within a valid range.
#define VERIFY_PEER_ID_IN_RANGE(id) \
do \
{ \
if (id >= PM_PEER_ID_N_AVAILABLE_IDS) \
{ \
return NRF_ERROR_INVALID_PARAM; \
} \
} while (0)
// Macro for verifying that the peer data id is withing a valid range.
#define VERIFY_PEER_DATA_ID_IN_RANGE(id) \
do \
{ \
if (!PM_PEER_DATA_ID_IS_VALID(id)) \
{ \
return NRF_ERROR_INVALID_PARAM; \
} \
} while (0)
// Macro for initializing the peer ID tracking system if it is not already initialized.
#define PEER_IDS_INITIALIZE() \
do \
{ \
if (!m_pds.peer_ids_initialized) \
{ \
peer_ids_init(); \
} \
} while (0)
typedef struct
{
bool peer_ids_initialized;
pds_evt_handler_t evt_handlers[MAX_REGISTRANTS];
uint8_t n_registrants;
bool clearing;
bool clear_queued;
} pds_t;
static pds_t m_pds = { .n_registrants = 0 };
#define MODULE_INITIALIZED (m_pds.n_registrants > 0) /**< Expression which is true when the module is initialized. */
#include "sdk_macros.h"
static void internal_state_reset(pds_t * p_pds)
{
memset(p_pds, 0, sizeof(pds_t));
}
// Function for dispatching outbound events to all registered event handlers.
static void pds_evt_send(pds_evt_t * p_event)
{
for (uint32_t i = 0; i < m_pds.n_registrants; i++)
{
m_pds.evt_handlers[i](p_event);
}
}
// Function to convert peer IDs to file IDs.
static uint16_t peer_id_to_file_id(pm_peer_id_t peer_id)
{
return (uint16_t)(peer_id + PEER_ID_TO_FILE_ID);
}
// Function to convert peer data id to type id.
static pm_peer_id_t file_id_to_peer_id(uint16_t file_id)
{
return (pm_peer_id_t)(file_id + FILE_ID_TO_PEER_ID);
}
// Function to convert peer data IDs to record keys.
static uint16_t peer_data_id_to_record_key(pm_peer_data_id_t peer_data_id)
{
return (uint16_t)peer_data_id + (uint16_t)PEER_DATA_ID_TO_RECORD_KEY;
}
// Function to convert record keys to peer data IDs.
static pm_peer_data_id_t record_key_to_peer_data_id(uint16_t record_key)
{
return (pm_peer_data_id_t)(record_key + RECORD_KEY_TO_PEER_DATA_ID);
}
// Function for clearing all peer data of one peer.
// These operations will be sent to FDS one at a time.
static void peer_data_clear()
{
ret_code_t retval;
uint16_t file_id;
fds_record_desc_t desc;
fds_find_token_t token = {0};
pm_peer_id_t peer_id = peer_id_get_next_deleted(PM_PEER_ID_INVALID);
while ( (peer_id != PM_PEER_ID_INVALID)
&& (fds_record_find_in_file(peer_id_to_file_id(peer_id), &desc, &token)
== FDS_ERR_NOT_FOUND))
{
peer_id_free(peer_id);
peer_id = peer_id_get_next_deleted(peer_id);
}
if (!m_pds.clearing && (peer_id != PM_PEER_ID_INVALID))
{
file_id = peer_id_to_file_id(peer_id);
retval = fds_file_delete(file_id);
if (retval == FDS_SUCCESS)
{
m_pds.clearing = true;
}
else if (retval == FDS_ERR_NO_SPACE_IN_QUEUES)
{
m_pds.clear_queued = true;
}
else
{
pds_evt_t pds_evt;
pds_evt.evt_id = PDS_EVT_ERROR_UNEXPECTED;
pds_evt.peer_id = peer_id;
pds_evt.data_id = PM_PEER_DATA_ID_INVALID;
pds_evt.store_token = PM_STORE_TOKEN_INVALID;
pds_evt.result = retval;
pds_evt_send(&pds_evt);
}
}
}
static ret_code_t find_fds_item(pm_peer_id_t peer_id,
pm_peer_data_id_t data_id,
fds_record_desc_t * const p_desc)
{
fds_find_token_t find_tok = {0};
VERIFY_PEER_ID_IN_RANGE(peer_id);
VERIFY_PEER_DATA_ID_IN_RANGE(data_id);
// pp_record verified by caller.
uint16_t file_id = peer_id_to_file_id(peer_id);
uint16_t record_key = peer_data_id_to_record_key(data_id);
return fds_record_find(file_id, record_key, p_desc, &find_tok);
}
static void peer_ids_init()
{
fds_record_desc_t record_desc;
fds_flash_record_t record;
fds_find_token_t find_tok = {0};
uint16_t const record_key = peer_data_id_to_record_key(PM_PEER_DATA_ID_BONDING);
if (!m_pds.peer_ids_initialized)
{
while(fds_record_find_by_key(record_key, &record_desc, &find_tok) == FDS_SUCCESS)
{
pm_peer_id_t peer_id;
// It is safe to ignore the return value since we just obtained
// this descriptor and also 'record' is different from NULL.
(void)fds_record_open(&record_desc, &record);
peer_id = file_id_to_peer_id(record.p_header->ic.file_id);
(void)fds_record_close(&record_desc);
(void)peer_id_allocate(peer_id);
}
m_pds.peer_ids_initialized = true;
}
}
static void fds_evt_handler(fds_evt_t const * const p_fds_evt)
{
pds_evt_t pds_evt;
bool send_event = true;
pds_evt.result = (p_fds_evt->result == FDS_SUCCESS);
switch(p_fds_evt->id)
{
case FDS_EVT_WRITE:
pds_evt.evt_id = (p_fds_evt->result == FDS_SUCCESS) ? PDS_EVT_STORED :
PDS_EVT_ERROR_STORE;
pds_evt.peer_id = file_id_to_peer_id(p_fds_evt->write.file_id);
pds_evt.data_id = record_key_to_peer_data_id(p_fds_evt->write.record_key);
pds_evt.result = p_fds_evt->result;
pds_evt.store_token = p_fds_evt->write.record_id;
break;
case FDS_EVT_UPDATE:
pds_evt.evt_id = (p_fds_evt->result == FDS_SUCCESS) ? PDS_EVT_UPDATED :
PDS_EVT_ERROR_UPDATE;
pds_evt.peer_id = file_id_to_peer_id(p_fds_evt->write.file_id);
pds_evt.data_id = record_key_to_peer_data_id(p_fds_evt->write.record_key);
pds_evt.result = p_fds_evt->result;
pds_evt.store_token = p_fds_evt->write.record_id;
break;
case FDS_EVT_DEL_RECORD:
pds_evt.evt_id = (p_fds_evt->result == FDS_SUCCESS) ? PDS_EVT_CLEARED :
PDS_EVT_ERROR_CLEAR;
pds_evt.peer_id = file_id_to_peer_id(p_fds_evt->del.file_id);
pds_evt.data_id = record_key_to_peer_data_id(p_fds_evt->del.record_key);
pds_evt.store_token = p_fds_evt->del.record_id;
break;
case FDS_EVT_DEL_FILE:
{
if ((p_fds_evt->del.record_key == FDS_RECORD_KEY_DIRTY) &&
(p_fds_evt->del.file_id != FDS_FILE_ID_INVALID))
{
pds_evt.peer_id = file_id_to_peer_id(p_fds_evt->del.file_id);
pds_evt.data_id = record_key_to_peer_data_id(p_fds_evt->del.record_key);
pds_evt.data_id = PM_PEER_DATA_ID_INVALID;
if (p_fds_evt->result == FDS_SUCCESS)
{
pds_evt.evt_id = PDS_EVT_PEER_ID_CLEAR;
peer_id_free(pds_evt.peer_id);
}
else
{
pds_evt.evt_id = PDS_EVT_ERROR_PEER_ID_CLEAR;
}
m_pds.clearing = false;
m_pds.clear_queued = false;
peer_data_clear();
}
}
break;
case FDS_EVT_GC:
pds_evt.evt_id = PDS_EVT_COMPRESSED;
break;
default:
send_event = false;
break;
}
if (send_event)
{
pds_evt_send(&pds_evt);
}
if (m_pds.clear_queued)
{
m_pds.clear_queued = false;
peer_data_clear();
}
}
ret_code_t pds_register(pds_evt_handler_t evt_handler)
{
if (m_pds.n_registrants >= MAX_REGISTRANTS)
{
return NRF_ERROR_NO_MEM;
}
VERIFY_PARAM_NOT_NULL(evt_handler);
if (!MODULE_INITIALIZED)
{
ret_code_t retval;
internal_state_reset(&m_pds);
peer_id_init();
retval = fds_register(fds_evt_handler);
if (retval != FDS_SUCCESS)
{
return NRF_ERROR_NO_MEM;
}
retval = fds_init();
if (retval != FDS_SUCCESS)
{
return NRF_ERROR_INTERNAL;
}
}
m_pds.evt_handlers[m_pds.n_registrants] = evt_handler;
m_pds.n_registrants += 1;
return NRF_SUCCESS;
}
ret_code_t pds_peer_data_read_ptr_get(pm_peer_id_t peer_id,
pm_peer_data_id_t data_id,
pm_peer_data_flash_t * p_data,
pm_store_token_t * p_token)
{
ret_code_t retval;
fds_flash_record_t record;
fds_record_desc_t record_desc;
VERIFY_MODULE_INITIALIZED();
VERIFY_PEER_ID_IN_RANGE(peer_id);
VERIFY_PEER_DATA_ID_IN_RANGE(data_id);
VERIFY_PARAM_NOT_NULL(p_data);
retval = find_fds_item(peer_id, data_id, &record_desc);
if (retval != FDS_SUCCESS)
{
return NRF_ERROR_NOT_FOUND;
}
// Shouldn't fail, unless the record was deleted.
(void)fds_record_open(&record_desc, &record);
if (p_data != NULL)
{
p_data->data_id = data_id;
p_data->length_words = record.p_header->tl.length_words;
p_data->p_all_data = record.p_data;
}
if (p_token != NULL)
{
*p_token = (uint32_t)record.p_header->record_id;
}
// Shouldn't fail, unless the record was already closed.
(void)fds_record_close(&record_desc);
return NRF_SUCCESS;
}
ret_code_t pds_peer_data_lock(pm_store_token_t store_token)
{
VERIFY_MODULE_INITIALIZED();
VERIFY_PARAM_NOT_ZERO(store_token);
// TODO: Not implemented in fds yet.
return NRF_SUCCESS;
}
ret_code_t pds_peer_data_verify(pm_store_token_t store_token)
{
VERIFY_MODULE_INITIALIZED();
VERIFY_PARAM_NOT_ZERO(store_token);
// TODO: Not implemented in fds yet.
return NRF_SUCCESS;
}
ret_code_t pds_peer_data_read(pm_peer_id_t peer_id,
pm_peer_data_id_t data_id,
pm_peer_data_t * p_data,
uint16_t * p_len_words)
{
ret_code_t retval;
pm_peer_data_flash_t peer_data_flash;
VERIFY_PEER_ID_IN_RANGE(peer_id);
VERIFY_PEER_DATA_ID_IN_RANGE(data_id);
VERIFY_PARAM_NOT_NULL(p_len_words);
VERIFY_PARAM_NOT_NULL(p_data);
retval = pds_peer_data_read_ptr_get(peer_id, data_id, &peer_data_flash, NULL);
if (retval != NRF_SUCCESS)
{
return retval;
}
if ((*p_len_words) == 0)
{
(*p_len_words) = peer_data_flash.length_words;
return NRF_SUCCESS;
}
else if ((*p_len_words) < peer_data_flash.length_words)
{
return NRF_ERROR_NO_MEM;
}
VERIFY_PARAM_NOT_NULL(p_data->p_all_data);
retval = peer_data_deserialize(&peer_data_flash, p_data);
return retval;
}
ret_code_t pds_peer_data_write_prepare(pm_peer_data_const_t const * p_peer_data,
pm_prepare_token_t * p_prepare_token)
{
ret_code_t retval;
VERIFY_MODULE_INITIALIZED();
VERIFY_PARAM_NOT_NULL(p_peer_data);
VERIFY_PEER_DATA_ID_IN_RANGE(p_peer_data->data_id);
//VERIFY_PARAM_NOT_NULL(p_prepare_token); redundant, see fds_reserve().
retval = fds_reserve((fds_reserve_token_t*)p_prepare_token, p_peer_data->length_words);
switch (retval)
{
case FDS_SUCCESS:
return NRF_SUCCESS;
case FDS_ERR_NULL_ARG:
return NRF_ERROR_NULL;
case FDS_ERR_RECORD_TOO_LARGE:
return NRF_ERROR_INVALID_LENGTH;
case FDS_ERR_NO_SPACE_IN_FLASH:
return NRF_ERROR_NO_MEM;
default:
return NRF_ERROR_INTERNAL;
}
}
ret_code_t pds_peer_data_write_prepare_cancel(pm_prepare_token_t prepare_token)
{
ret_code_t retval;
VERIFY_MODULE_INITIALIZED();
VERIFY_PARAM_NOT_ZERO(prepare_token);
retval = fds_reserve_cancel((fds_reserve_token_t*)&prepare_token);
switch (retval)
{
case FDS_SUCCESS:
return NRF_SUCCESS;
case FDS_ERR_NULL_ARG:
return NRF_ERROR_NULL;
default:
return NRF_ERROR_INTERNAL;
}
}
ret_code_t pds_peer_data_write_prepared(pm_peer_id_t peer_id,
pm_peer_data_const_t const * p_peer_data,
pm_prepare_token_t prepare_token,
pm_store_token_t * p_store_token)
{
ret_code_t retval;
fds_record_t record;
fds_record_desc_t record_desc;
fds_record_chunk_t chunks[2];
uint16_t n_chunks;
VERIFY_MODULE_INITIALIZED();
VERIFY_PEER_ID_IN_RANGE(peer_id);
VERIFY_PARAM_NOT_NULL(p_peer_data);
VERIFY_PEER_DATA_ID_IN_RANGE(p_peer_data->data_id);
VERIFY_PARAM_NOT_ZERO(prepare_token);
// Create chunks.
peer_data_parts_get(p_peer_data, chunks, &n_chunks);
// Prepare the record to be written.
record.file_id = peer_id_to_file_id(peer_id);
record.key = peer_data_id_to_record_key(p_peer_data->data_id);
record.data.p_chunks = chunks;
record.data.num_chunks = n_chunks;
retval = fds_record_write_reserved(&record_desc,
&record,
(fds_reserve_token_t*)&prepare_token);
if ((retval == FDS_SUCCESS) && (p_store_token != NULL))
{
// If fds_record_write_reserved() returned sucessfully, it is safe
// to ignore the return value from fds_record_id_from_desc() since
// the descriptor is valid, and also p_store_token is different from NULL.
(void)fds_record_id_from_desc(&record_desc, (uint32_t*)p_store_token);
}
switch (retval)
{
case FDS_SUCCESS:
return NRF_SUCCESS;
case FDS_ERR_BUSY:
case FDS_ERR_NO_SPACE_IN_QUEUES:
return NRF_ERROR_BUSY;
default:
return NRF_ERROR_INTERNAL;
}
}
ret_code_t pds_peer_data_write(pm_peer_id_t peer_id,
pm_peer_data_const_t const * p_peer_data,
pm_store_token_t * p_store_token)
{
ret_code_t retval;
fds_record_t record;
fds_record_desc_t record_desc;
fds_record_chunk_t chunks[2];
uint16_t n_chunks;
VERIFY_MODULE_INITIALIZED();
VERIFY_PEER_ID_IN_RANGE(peer_id);
VERIFY_PARAM_NOT_NULL(p_peer_data);
VERIFY_PEER_DATA_ID_IN_RANGE(p_peer_data->data_id);
// Create chunks.
peer_data_parts_get(p_peer_data, chunks, &n_chunks);
// Prepare the record to be written.
record.file_id = peer_id_to_file_id(peer_id);
record.key = peer_data_id_to_record_key(p_peer_data->data_id);
record.data.p_chunks = chunks;
record.data.num_chunks = n_chunks;
retval = fds_record_write(&record_desc, &record);
if ((retval == FDS_SUCCESS) && (p_store_token != NULL))
{
// If fds_record_write() returned sucessfully, it is safe
// to ignore the return value from fds_record_id_from_desc() since
// the descriptor is valid, and also p_store_token is different from NULL.
(void)fds_record_id_from_desc(&record_desc, (uint32_t*)p_store_token);
}
switch (retval)
{
case FDS_SUCCESS:
return NRF_SUCCESS;
case FDS_ERR_BUSY:
case FDS_ERR_NO_SPACE_IN_QUEUES:
return NRF_ERROR_BUSY;
case FDS_ERR_NO_SPACE_IN_FLASH:
return NRF_ERROR_NO_MEM;
default:
return NRF_ERROR_INTERNAL;
}
}
ret_code_t pds_peer_data_update(pm_peer_id_t peer_id,
pm_peer_data_const_t const * p_peer_data,
pm_store_token_t old_token,
pm_store_token_t * p_store_token)
{
ret_code_t retval;
fds_record_t record;
fds_record_desc_t record_desc;
fds_record_chunk_t chunks[2];
uint16_t n_chunks;
VERIFY_MODULE_INITIALIZED();
VERIFY_PEER_ID_IN_RANGE(peer_id);
VERIFY_PARAM_NOT_NULL(p_peer_data);
VERIFY_PEER_DATA_ID_IN_RANGE(p_peer_data->data_id);
// Create chunks.
peer_data_parts_get(p_peer_data, chunks, &n_chunks);
// Prepare the record to be written.
record.file_id = peer_id_to_file_id(peer_id);
record.key = peer_data_id_to_record_key(p_peer_data->data_id);
record.data.p_chunks = chunks;
record.data.num_chunks = n_chunks;
// Obtain the descriptor of the record to be updated.
// It is safe to ignore the return value if record_desc is different from NULL.
(void)fds_descriptor_from_rec_id(&record_desc, (uint32_t)old_token);
retval = fds_record_update(&record_desc, &record);
if ((retval == FDS_SUCCESS) && (p_store_token != NULL))
{
// If fds_record_update() returned sucessfully, it is safe
// to ignore the return value from fds_record_id_from_desc() since
// the descriptor is valid, and also p_store_token is different from NULL.
(void)fds_record_id_from_desc(&record_desc, (uint32_t*)p_store_token);
}
switch (retval)
{
case FDS_SUCCESS:
return NRF_SUCCESS;
case FDS_ERR_BUSY:
case FDS_ERR_NO_SPACE_IN_QUEUES:
return NRF_ERROR_BUSY;
case FDS_ERR_NO_SPACE_IN_FLASH:
return NRF_ERROR_NO_MEM;
default:
return NRF_ERROR_INTERNAL;
}
}
ret_code_t pds_peer_data_clear(pm_peer_id_t peer_id, pm_peer_data_id_t data_id)
{
ret_code_t retval;
uint16_t file_id;
uint16_t record_key;
fds_record_desc_t record_desc;
fds_find_token_t find_tok = {0};
VERIFY_MODULE_INITIALIZED();
VERIFY_PEER_ID_IN_RANGE(peer_id);
VERIFY_PEER_DATA_ID_IN_RANGE(data_id);
file_id = peer_id_to_file_id(peer_id);
record_key = peer_data_id_to_record_key(data_id);
retval = fds_record_find(file_id, record_key, &record_desc, &find_tok);
if(retval != FDS_SUCCESS)
{
return NRF_ERROR_NOT_FOUND;
}
retval = fds_record_delete(&record_desc);
switch (retval)
{
case FDS_SUCCESS:
return NRF_SUCCESS;
case FDS_ERR_NO_SPACE_IN_QUEUES:
return NRF_ERROR_BUSY;
default:
return NRF_ERROR_INTERNAL;
}
}
pm_peer_id_t pds_peer_id_allocate(void)
{
if (!MODULE_INITIALIZED)
{
return PM_PEER_ID_INVALID;
}
PEER_IDS_INITIALIZE();
return peer_id_allocate(PM_PEER_ID_INVALID);
}
ret_code_t pds_peer_id_free(pm_peer_id_t peer_id)
{
VERIFY_MODULE_INITIALIZED();
VERIFY_PEER_ID_IN_RANGE(peer_id);
PEER_IDS_INITIALIZE();
(void)peer_id_delete(peer_id);
peer_data_clear();
return NRF_SUCCESS;
}
bool pds_peer_id_is_allocated(pm_peer_id_t peer_id)
{
if (!MODULE_INITIALIZED)
{
return false;
}
PEER_IDS_INITIALIZE();
return peer_id_is_allocated(peer_id);
}
pm_peer_id_t pds_next_peer_id_get(pm_peer_id_t prev_peer_id)
{
if (!MODULE_INITIALIZED)
{
return PM_PEER_ID_INVALID;
}
PEER_IDS_INITIALIZE();
return peer_id_get_next_used(prev_peer_id);
}
uint32_t pds_n_peers(void)
{
if (!MODULE_INITIALIZED)
{
return 0;
}
PEER_IDS_INITIALIZE();
return peer_id_n_ids();
}
//lint -restore

View File

@ -1,381 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 PEER_DATA_STORAGE_H__
#define PEER_DATA_STORAGE_H__
#include <stdint.h>
#include "sdk_errors.h"
#include "nrf_ble_gap.h"
#include "peer_manager_types.h"
#include "peer_manager_internal.h"
/**
* @cond NO_DOXYGEN
* @defgroup peer_data_storage Peer Data Storage
* @ingroup peer_manager
* @{
* @brief An internal module of @ref peer_manager. This module provides a Peer Manager-specific API
* to the persistent storage.
*/
#define PDS_PREPARE_TOKEN_INVALID 0 /**< Invalid value for prepare token. */
enum
{
PEER_ID_TO_FILE_ID = 0xC000,
FILE_ID_TO_PEER_ID = -PEER_ID_TO_FILE_ID,
PEER_DATA_ID_TO_RECORD_KEY = 0xC000,
RECORD_KEY_TO_PEER_DATA_ID = -PEER_DATA_ID_TO_RECORD_KEY,
};
/**@brief The types of events that can come from the peer_data_storage module.
*/
typedef enum
{
PDS_EVT_STORED, /**< The specified data has been successfully stored. */
PDS_EVT_UPDATED, /**< The specified data has been successfully updated. */
PDS_EVT_CLEARED, /**< The specified data has been successfully cleared. */
PDS_EVT_ERROR_STORE, /**< The specified data could not be stored. */
PDS_EVT_ERROR_UPDATE, /**< The specified data could not be updated. */
PDS_EVT_ERROR_CLEAR, /**< The specified data could not be cleared. */
PDS_EVT_PEER_ID_CLEAR, /**< The peer id has been successfully cleared. */
PDS_EVT_ERROR_PEER_ID_CLEAR, /**< The peer id has been successfully cleared. */
PDS_EVT_COMPRESSED, /**< A compress procedure has finished successfully. */
PDS_EVT_ERROR_UNEXPECTED, /**< An unexpected, possibly fatal error occurred. The unexpected error is included in the event structure. */
} pds_evt_id_t;
/**@brief Events that can come from the peer_data_storage module.
*/
typedef struct
{
pds_evt_id_t evt_id; /**< The type of event. */
pm_peer_id_t peer_id; /**< The peer the event pertains to. */
pm_peer_data_id_t data_id; /**< The data the event pertains to. */
pm_store_token_t store_token; /**< A unique identifier for the operation. Can be compare to the token received when starting the operation. */
ret_code_t result; /**< The result of the operation, or the unexpected error. */
} pds_evt_t;
/**@brief Event handler for events from the peer_data_storage module.
*
* @param[in] event The event that has happened.
* @param[in] peer_id The id of the peer the event pertains to.
* @param[in] flags The data the event pertains to.
*/
typedef void (*pds_evt_handler_t)(pds_evt_t const * p_event);
/**@brief Function for registering for events from the peer database.
*
* @note This function will initialize the module if it is not already initialized.
*
* @param[in] evt_handler Event handler to register.
*
* @retval NRF_SUCCESS Registration successful.
* @retval NRF_ERROR_NO_MEM No more event handlers can be registered.
* @retval NRF_ERROR_NULL evt_handler was NULL.
* @retval NRF_ERROR_INTERNAL An unexpected error happened.
* @retval NRF_ERROR_INTERNAL Unexpected error.
*/
ret_code_t pds_register(pds_evt_handler_t evt_handler);
/**@brief Function for retrieving a direct pointer to peer data in persistent storage.
*
* @param[in] peer_id The id of the peer whose data to read.
* @param[in] data_id Which data to get.
* @param[out] p_data The peer data pointer.
* @param[out] p_token Token that can be used to lock data in flash and check data validity.
*
* @retval NRF_SUCCESS The pointer was successfully retrieved.
* @retval NRF_ERROR_INVALID_PARAM Invalid data_id.
* @retval NRF_ERROR_NOT_FOUND The requested data was not found in persistent storage.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t pds_peer_data_read_ptr_get(pm_peer_id_t peer_id,
pm_peer_data_id_t data_id,
pm_peer_data_flash_t * p_data,
pm_store_token_t * p_token);
#if 0
// @TODO: Finish documentation
/**@brief Function to lock the flash data (to defer compression from invalidating data)
*
* @param[in] store_token The token representing the item to lock
*
* @retval NRF_SUCCESS Successfully locked
*/
ret_code_t pds_peer_data_lock(pm_store_token_t store_token);
/**@brief Function to verify flash data integrity
*
* @param[in] store_token The token representing the item to lock
*
* @retval NRF_SUCCESS The data integrity is valid.
* @retval NRF_ERROR_NULL The token is invalid.
* @retval NRF_ERROR_INVALID_DATA The data integrity is not valid.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t pds_peer_data_verify(pm_store_token_t store_token);
#endif
/**@brief Function for retrieving peer data from persistent storage by making a copy.
*
* @param[in] peer_id The id of the peer whose data to read.
* @param[in] data_id Which piece of data to read.
* @param[out] p_data Pointer to the peer data.
* @param[in,out] p_len_words Length available to copy to (in words).
* If set to NULL, then no copy will be made and the
* length will be reflected in p_len_words after the call returns.
*
* @retval NRF_SUCCESS The read was successful.
* @retval NRF_ERROR_INVALID_PARAM Invalid data_id or peer_id.
* @retval NRF_ERROR_NULL Either \c p_data or \c p_len_words were \c NULL, or \c p_data
* contained a NULL pointer.
* @retval NRF_ERROR_NOT_FOUND The requested data was not found in persistent storage.
* @retval NRF_ERROR_NO_MEM The length of stored data too large to copy out.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t pds_peer_data_read(pm_peer_id_t peer_id,
pm_peer_data_id_t data_id,
pm_peer_data_t * p_data,
uint16_t * p_len_words);
/**@brief Function for preparing persistent storage for a write.
*
* @details If this call succeeds, space is reserved in persistent storage, so the write will fit.
*
* @note If space has already been prepared for this peer_id/data_id pair, no new space will be
* reserved, unless the previous reservation had too small size.
*
* @param[in] p_peer_data Data to prepare for. The data needs not be ready, but length and type
* values must.
* @param[out] p_prepare_token A token identifying the prepared memory area.
*
* @retval NRF_SUCCESS The call was successful.
* @retval NRF_ERROR_NULL Either \c p_peer_data or \c p_prepare code were \c NULL.
* @retval NRF_ERROR_INVALID_PARAM Invalid data ID.
* @retval NRF_ERROR_INVALID_LENGTH Data length exceeds the maximum length allowed.
* @retval NRF_ERROR_NO_MEM No space available in persistent storage.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
* @retval NRF_ERROR_INTERNAL Internal error.
*/
ret_code_t pds_peer_data_write_prepare(pm_peer_data_const_t const * p_peer_data,
pm_prepare_token_t * p_prepare_token);
/**@brief Function for undoing a previous call to @ref pds_peer_data_write_prepare.
*
* @param[in] prepare_token A token identifying the prepared memory area to cancel.
*
* @retval NRF_SUCCESS The call was successful.
* @retval NRF_ERROR_NULL Invalid value for \c prepare_token.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
* @retval NRF_ERROR_INTERNAL Internal error.
*/
ret_code_t pds_peer_data_write_prepare_cancel(pm_prepare_token_t prepare_token);
/**@brief Function for writing prepared (reserved) peer data to persistent storage.
*
* @details Writing happens asynchronously. Expect a @ref PDS_EVT_STORED or @ref PDS_EVT_ERROR_STORE
* event.
*
* @param[in] peer_id The id of the peer the data pertains to.
* @param[in] p_peer_data The peer data.
* @param[in] prepare_token A token identifying the prepared memory area to write into. If
* the prepare token is invalid, e.g. PDS_PREPARE_TOKEN_INVALID, the
* prepare/write sequence will happen atomically.
* @param[out] p_store_token A token identifying this particular store operation. The token can be
* used to identify events pertaining to this operation.
*
* @retval NRF_SUCCESS The write was initiated successfully.
* @retval NRF_ERROR_INVALID_PARAM Invalid peer ID or data ID.
* @retval NRF_ERROR_NULL \c p_peer_data was \c NULL or contained a \c NULL pointer or
* \c prepare_token was zero.
* @retval NRF_ERROR_NO_MEM No space available in persistent storage. This can only happen
* if \c p_prepare_token is \c NULL.
* @retval NRF_ERROR_BUSY FDS or underlying modules are busy and can't take any
* more requests.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
* @retval NRF_ERROR_INTERNAL Internal error.
*/
ret_code_t pds_peer_data_write_prepared(pm_peer_id_t peer_id,
pm_peer_data_const_t const * p_peer_data,
pm_prepare_token_t prepare_token,
pm_store_token_t * p_store_token);
/**@brief Function for writing peer data to persistent storage.
*
* @details Writing happens asynchronously. Expect a @ref PDS_EVT_STORED or @ref PDS_EVT_ERROR_STORE
* event.
*
* @param[in] peer_id The id of the peer the data pertains to.
* @param[in] p_peer_data The peer data.
* @param[out] p_store_token A token identifying this particular store operation. The token can be
* used to identify events pertaining to this operation.
*
* @retval NRF_SUCCESS The write was initiated successfully.
* @retval NRF_ERROR_INVALID_PARAM Invalid data ID or peer ID.
* @retval NRF_ERROR_NULL \c p_peer_data was \c NULL or data contained a \c NULL pointer.
* @retval NRF_ERROR_NO_MEM No space available in persistent storage.
* @retval NRF_ERROR_BUSY FDS or underlying modules are busy and can't take any
* more requests.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
* @retval NRF_ERROR_INTERNAL Internal error.
*/
ret_code_t pds_peer_data_write(pm_peer_id_t peer_id,
pm_peer_data_const_t const * p_peer_data,
pm_store_token_t * p_store_token);
/**@brief Function for updating currently stored peer data to a new version
*
* @details Updating happens asynchronously.
* Expect a @ref PDS_EVT_STORED or @ref PDS_EVT_ERROR_STORE for the store token
* and a @ref PDS_EVT_ERROR_CLEAR or @ref PDS_EVT_ERROR_CLEAR for the old token
*
* @param[in] peer_id The peer which the data is associated to.
* @param[in] p_peer_data New data.
* @param[in] old_token Store token for the old data.
* @param[out] p_store_token Store token for the new data.
*
* @retval NRF_SUCESS The update was initiated successfully
* @retval NRF_ERROR_NULL \c p_peer_data was \c NULL or data contained a \c NULL pointer.
* @retval NRF_ERROR_NO_MEM No space available in persistent storage.
* @retval NRF_ERROR_BUSY FDS or underlying modules are busy and can't take any
* more requests at this moment.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
* @retval NRF_ERROR_INTERNAL Internal error.
*/
ret_code_t pds_peer_data_update(pm_peer_id_t peer_id,
pm_peer_data_const_t const * p_peer_data,
pm_store_token_t old_token,
pm_store_token_t * p_store_token);
/**@brief Function for clearing peer data from persistent storage.
*
* @details Clearing happens asynchronously. Expect a @ref PDS_EVT_CLEARED or @ref PDS_EVT_ERROR_CLEAR
* event.
*
* @param[in] peer_id The id of the peer the data pertains to.
* @param[in] data_id Which data to clear.
*
* @retval NRF_SUCCESS The clear was initiated successfully.
* @retval NRF_ERROR_INVALID_PARAM Data ID or peer ID was invalid.
* @retval NRF_ERROR_NOT_FOUND Nothing to clear for this peer ID.
* @retval NRF_ERROR_BUSY FDS or underlying modules are busy and can't take any
* more requests at this moment.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
* @retval NRF_ERROR_INTERNAL Internal error.
*/
ret_code_t pds_peer_data_clear(pm_peer_id_t peer_id, pm_peer_data_id_t data_id);
/**@brief Function for claiming an unused peer ID.
*
* @return The first unused peer ID.
* @retval PM_PEER_ID_INVALID If no peer ID is available or module is not initialized.
*/
pm_peer_id_t pds_peer_id_allocate(void);
/**@brief Function for freeing a peer ID and clearing all data associated with it in persistent
* storage.
*
* @param[in] peer_id Peer ID to free.
*
* @retval NRF_SUCCESS The clear was initiated successfully.
* @retval NRF_ERROR_INVALID_STATE Module not initialized.
* @retval NRF_ERROR_INVALID_PARAM Invalid peer ID.
*/
ret_code_t pds_peer_id_free(pm_peer_id_t peer_id);
/**@brief Function for finding out whether a peer ID is in use.
*
* @param[in] peer_id The peer ID to inquire about.
*
* @retval true peer_id is in use.
* @retval false peer_id is free, or the module is not initialized.
*/
bool pds_peer_id_is_allocated(pm_peer_id_t peer_id);
/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. Can be
* used to loop through all used peer IDs.
*
* @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary
* peer ID.
*
* @param[in] prev_peer_id The previous peer ID.
*
* @return The next peer ID.
* @return The first ordinary peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID.
* @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID or the module
* is not initialized.
*/
pm_peer_id_t pds_next_peer_id_get(pm_peer_id_t prev_peer_id);
/**@brief Function for querying the number of valid peer IDs available. I.E the number of peers
* in persistent storage.
*
* @return The number of valid peer IDs, or 0 if module is not initialized.
*/
uint32_t pds_n_peers(void);
/** @}
* @endcond
*/
#endif /* PEER_DATA_STORAGE_H__ */

View File

@ -1,804 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "peer_database.h"
#include <string.h>
#include "app_util.h"
#include "peer_manager_types.h"
#include "peer_manager_internal.h"
#include "peer_data_storage.h"
#include "pm_buffer.h"
#include "sdk_common.h"
#define MAX_REGISTRANTS 6 /**< The number of user that can register with the module. */
#define N_WRITE_BUFFERS 8 /**< The number of write buffers available. */
#define N_WRITE_BUFFER_RECORDS (N_WRITE_BUFFERS) /**< The number of write buffer records. */
/**@brief Macro for verifying that the data ID is among the values eligible for using the write buffer.
*
* @param[in] data_id The data ID to verify.
*/
#define VERIFY_DATA_ID_WRITE_BUF(data_id) \
do \
{ \
if (((data_id) != PM_PEER_DATA_ID_BONDING) && ((data_id) != PM_PEER_DATA_ID_GATT_LOCAL)) \
{ \
return NRF_ERROR_INVALID_PARAM; \
} \
} while(0)
/**@brief Struct for keeping track of one write buffer, from allocation, until it is fully written
* or cancelled.
*/
typedef struct
{
pm_peer_id_t peer_id; /**< The peer ID this buffer belongs to. */
pm_peer_data_id_t data_id; /**< The data ID this buffer belongs to. */
uint8_t buffer_block_id; /**< The index of the first (or only) buffer block containing peer data. */
uint32_t n_bufs; /**< The number of buffer blocks containing peer data. */
uint8_t store_busy : 1; /**< Flag indicating that the buffer was attempted written to flash, but a busy error was returned and the operation should be retried. */
uint8_t store_flash_full : 1; /**< Flag indicating that the buffer was attempted written to flash, but a flash full error was returned and the operation should be retried after room has been made. */
uint8_t store_requested : 1; /**< Flag indicating that the buffer is being written to flash. */
pm_prepare_token_t prepare_token; /**< Token given by Peer Data Storage if room in flash has been reserved. */
pm_store_token_t store_token; /**< Token given by Peer Data Storage when a flash write has been successfully requested. */
} pdb_buffer_record_t;
/**@brief Struct for keeping track of the state of the module.
*/
typedef struct
{
pdb_evt_handler_t evt_handlers[MAX_REGISTRANTS]; /**< All registered event handlers. */
uint8_t n_registrants; /**< The number of registered event handlers. */
pm_buffer_t write_buffer; /**< The state of the write buffer. */
pdb_buffer_record_t write_buffer_records[N_WRITE_BUFFER_RECORDS]; /**< The available write buffer records. */
uint32_t n_writes; /**< The number of pending (Not yet successfully requested in Peer Data Storage) store operations. */
} pdb_t;
static pdb_t m_pdb = {.n_registrants = 0}; /**< The state of the module. */
#define MODULE_INITIALIZED (m_pdb.n_registrants > 0) /**< Expression which is true when the module is initialized. */
#include "sdk_macros.h"
/**@brief Function for invalidating a record of a write buffer allocation.
*
* @param[in] p_record The record to invalidate.
*/
static void write_buffer_record_invalidate(pdb_buffer_record_t * p_record)
{
p_record->peer_id = PM_PEER_ID_INVALID;
p_record->data_id = PM_PEER_DATA_ID_INVALID;
p_record->buffer_block_id = BUFFER_INVALID_ID;
p_record->store_busy = false;
p_record->store_flash_full = false;
p_record->store_requested = false;
p_record->n_bufs = 0;
p_record->prepare_token = PDS_PREPARE_TOKEN_INVALID;
p_record->store_token = PM_STORE_TOKEN_INVALID;
}
/**@brief Function for finding a record of a write buffer allocation.
*
* @param[in] peer_id The peer ID in the record.
* @param[inout] p_index In: The starting index, out: The index of the record
*
* @return A pointer to the matching record, or NULL if none was found.
*/
static pdb_buffer_record_t * write_buffer_record_find_next(pm_peer_id_t peer_id, int * p_index)
{
for (uint32_t i = *p_index; i < N_WRITE_BUFFER_RECORDS; i++)
{
if ((m_pdb.write_buffer_records[i].peer_id == peer_id))
{
return &m_pdb.write_buffer_records[i];
}
}
return NULL;
}
/**@brief Function for finding a record of a write buffer allocation.
*
* @param[in] peer_id The peer ID in the record.
* @param[in] data_id The data ID in the record.
*
* @return A pointer to the matching record, or NULL if none was found.
*/
static pdb_buffer_record_t * write_buffer_record_find(pm_peer_id_t peer_id,
pm_peer_data_id_t data_id)
{
int index = 0;
pdb_buffer_record_t * p_record = write_buffer_record_find_next(peer_id, &index);
while ((p_record != NULL) && (p_record->data_id != data_id))
{
index++;
p_record = write_buffer_record_find_next(peer_id, &index);
}
return p_record;
}
/**@brief Function for finding an available record for write buffer allocation.
*
* @return A pointer to the available record, or NULL if none was found.
*/
static pdb_buffer_record_t * write_buffer_record_find_unused(void)
{
return write_buffer_record_find(PM_PEER_ID_INVALID, PM_PEER_DATA_ID_INVALID);
}
/**@brief Function for gracefully deactivating a write buffer record.
*
* @details This function will first release any buffers, then invalidate the record.
*
* @param[inout] p_write_buffer_record The record to release.
*
* @return A pointer to the matching record, or NULL if none was found.
*/
static void write_buffer_record_release(pdb_buffer_record_t * p_write_buffer_record)
{
for (uint32_t i = 0; i < p_write_buffer_record->n_bufs; i++)
{
pm_buffer_release(&m_pdb.write_buffer, p_write_buffer_record->buffer_block_id + i);
}
write_buffer_record_invalidate(p_write_buffer_record);
}
/**@brief Function for claiming and activating a write buffer record.
*
* @param[out] pp_write_buffer_record The claimed record.
* @param[in] peer_id The peer ID this record should have.
* @param[in] data_id The data ID this record should have.
*/
static void write_buffer_record_get(pdb_buffer_record_t ** pp_write_buffer_record, pm_peer_id_t peer_id, pm_peer_data_id_t data_id)
{
if (pp_write_buffer_record == NULL)
{
return;
}
*pp_write_buffer_record = write_buffer_record_find_unused();
if (*pp_write_buffer_record == NULL)
{
// This also means the buffer is full.
return;
}
(*pp_write_buffer_record)->peer_id = peer_id;
(*pp_write_buffer_record)->data_id = data_id;
}
/**@brief Function for dispatching outbound events to all registered event handlers.
*
* @param[in] p_event The event to dispatch.
*/
static void pdb_evt_send(pdb_evt_t * p_event)
{
for (uint32_t i = 0; i < m_pdb.n_registrants; i++)
{
m_pdb.evt_handlers[i](p_event);
}
}
/**@brief Function for resetting the internal state of the Peer Database module.
*
* @param[out] p_event The event to dispatch.
*/
static void internal_state_reset(pdb_t * pdb)
{
memset(pdb, 0, sizeof(pdb_t));
for (uint32_t i = 0; i < N_WRITE_BUFFER_RECORDS; i++)
{
write_buffer_record_invalidate(&pdb->write_buffer_records[i]);
}
}
/**@brief Function for handling events from the Peer Data Storage module.
*
* @param[in] p_event The event to handle.
*/
static void pds_evt_handler(pds_evt_t const * p_event)
{
ret_code_t err_code;
pdb_buffer_record_t * p_write_buffer_record;
bool retry_flash_full = false;
pdb_evt_t event =
{
.peer_id = p_event->peer_id,
.data_id = p_event->data_id,
};
p_write_buffer_record = write_buffer_record_find(p_event->peer_id, p_event->data_id);
switch (p_event->evt_id)
{
case PDS_EVT_STORED:
case PDS_EVT_UPDATED:
if ( (p_write_buffer_record != NULL)
//&& (p_write_buffer_record->store_token == p_event->store_token)
&& (p_write_buffer_record->store_requested))
{
write_buffer_record_release(p_write_buffer_record);
event.evt_id = PDB_EVT_WRITE_BUF_STORED;
event.params.write_buf_stored_evt.update = (p_event->evt_id == PDS_EVT_UPDATED);
pdb_evt_send(&event);
}
else
{
event.evt_id = PDB_EVT_RAW_STORED;
event.params.raw_stored_evt.store_token = p_event->store_token;
pdb_evt_send(&event);
}
break;
case PDS_EVT_ERROR_STORE:
case PDS_EVT_ERROR_UPDATE:
if ( (p_write_buffer_record != NULL)
&& (p_write_buffer_record->store_token == p_event->store_token)
&& (p_write_buffer_record->store_requested))
{
// Retry if internal buffer.
m_pdb.n_writes++;
p_write_buffer_record->store_requested = false;
p_write_buffer_record->store_busy = true;
}
else
{
event.evt_id = PDB_EVT_RAW_STORE_FAILED;
event.params.error_raw_store_evt.err_code = p_event->result;
pdb_evt_send(&event);
}
break;
case PDS_EVT_CLEARED:
event.evt_id = PDB_EVT_CLEARED;
pdb_evt_send(&event);
break;
case PDS_EVT_ERROR_CLEAR:
event.evt_id = PDB_EVT_CLEAR_FAILED;
event.params.clear_failed_evt.err_code = p_event->result;
pdb_evt_send(&event);
break;
case PDS_EVT_PEER_ID_CLEAR:
event.evt_id = PDB_EVT_PEER_FREED;
pdb_evt_send(&event);
break;
case PDS_EVT_ERROR_PEER_ID_CLEAR:
event.evt_id = PDB_EVT_PEER_FREE_FAILED;
event.params.peer_free_failed_evt.err_code = p_event->result;
pdb_evt_send(&event);
break;
case PDS_EVT_COMPRESSED:
retry_flash_full = true;
event.evt_id = PDB_EVT_COMPRESSED;
pdb_evt_send(&event);
break;
case PDS_EVT_ERROR_UNEXPECTED:
event.params.error_unexpected.err_code = p_event->result;
break;
default:
break;
}
if (m_pdb.n_writes > 0)
{
for (uint32_t i = 0; i < N_WRITE_BUFFER_RECORDS; i++)
{
if ((m_pdb.write_buffer_records[i].store_busy)
|| (m_pdb.write_buffer_records[i].store_flash_full && retry_flash_full))
{
err_code = pdb_write_buf_store(m_pdb.write_buffer_records[i].peer_id,
m_pdb.write_buffer_records[i].data_id);
if (err_code != NRF_SUCCESS)
{
event.peer_id = m_pdb.write_buffer_records[i].peer_id;
event.data_id = m_pdb.write_buffer_records[i].data_id;
if (err_code == NRF_ERROR_NO_MEM)
{
event.evt_id = PDB_EVT_ERROR_NO_MEM;
}
else
{
event.evt_id = PDB_EVT_ERROR_UNEXPECTED;
event.params.error_unexpected.err_code = err_code;
}
pdb_evt_send(&event);
break;
}
}
}
}
}
ret_code_t pdb_register(pdb_evt_handler_t evt_handler)
{
if (m_pdb.n_registrants >= MAX_REGISTRANTS)
{
return NRF_ERROR_NO_MEM;
}
VERIFY_PARAM_NOT_NULL(evt_handler);
if (!MODULE_INITIALIZED)
{
ret_code_t err_code;
internal_state_reset(&m_pdb);
err_code = pds_register(pds_evt_handler);
if (err_code != NRF_SUCCESS)
{
return NRF_ERROR_INTERNAL;
}
PM_BUFFER_INIT(&m_pdb.write_buffer, N_WRITE_BUFFERS, PDB_WRITE_BUF_SIZE, err_code);
if (err_code != NRF_SUCCESS)
{
return NRF_ERROR_INTERNAL;
}
}
m_pdb.evt_handlers[m_pdb.n_registrants] = evt_handler;
m_pdb.n_registrants += 1;
return NRF_SUCCESS;
}
pm_peer_id_t pdb_peer_allocate(void)
{
if (!MODULE_INITIALIZED)
{
return PM_PEER_ID_INVALID;
}
return pds_peer_id_allocate();
}
ret_code_t pdb_peer_free(pm_peer_id_t peer_id)
{
VERIFY_MODULE_INITIALIZED();
ret_code_t err_code_in = NRF_SUCCESS;
ret_code_t err_code_out = NRF_SUCCESS;
int index = 0;
pdb_buffer_record_t * p_record = write_buffer_record_find_next(peer_id, &index);
while (p_record != NULL)
{
err_code_in = pdb_write_buf_release(peer_id, p_record->data_id);
if ( (err_code_in != NRF_SUCCESS)
&& (err_code_in != NRF_ERROR_NOT_FOUND))
{
err_code_out = NRF_ERROR_INTERNAL;
}
index++;
p_record = write_buffer_record_find_next(peer_id, &index);
}
if (err_code_out == NRF_SUCCESS)
{
err_code_in = pds_peer_id_free(peer_id);
if (err_code_in == NRF_SUCCESS)
{
// No action needed.
}
else if (err_code_in == NRF_ERROR_INVALID_PARAM)
{
err_code_out = NRF_ERROR_INVALID_PARAM;
}
else
{
err_code_out = NRF_ERROR_INTERNAL;
}
}
return err_code_out;
}
ret_code_t pdb_read_buf_get(pm_peer_id_t peer_id,
pm_peer_data_id_t data_id,
pm_peer_data_flash_t * p_peer_data,
pm_store_token_t * p_token)
{
VERIFY_MODULE_INITIALIZED();
return pds_peer_data_read_ptr_get(peer_id, data_id, p_peer_data, p_token);
}
static void peer_data_point_to_buffer(pm_peer_data_t * p_peer_data, pm_peer_data_id_t data_id, uint8_t * p_buffer_memory, uint16_t n_bufs)
{
uint16_t n_bytes = n_bufs * PDB_WRITE_BUF_SIZE;
p_peer_data->data_id = data_id;
p_peer_data->p_all_data = (pm_peer_data_bonding_t *)p_buffer_memory;
p_peer_data->length_words = BYTES_TO_WORDS(n_bytes);
}
static void peer_data_const_point_to_buffer(pm_peer_data_const_t * p_peer_data, pm_peer_data_id_t data_id, uint8_t * p_buffer_memory, uint32_t n_bufs)
{
peer_data_point_to_buffer((pm_peer_data_t*)p_peer_data, data_id, p_buffer_memory, n_bufs);
}
static void write_buf_length_words_set(pm_peer_data_const_t * p_peer_data)
{
switch (p_peer_data->data_id)
{
case PM_PEER_DATA_ID_BONDING:
p_peer_data->length_words = PM_BONDING_DATA_N_WORDS();
break;
case PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING:
p_peer_data->length_words = PM_SC_STATE_N_WORDS();
break;
case PM_PEER_DATA_ID_PEER_RANK:
p_peer_data->length_words = PM_USAGE_INDEX_N_WORDS();
break;
case PM_PEER_DATA_ID_GATT_LOCAL:
p_peer_data->length_words = PM_LOCAL_DB_N_WORDS(p_peer_data->p_local_gatt_db->len);
break;
default:
// No action needed.
break;
}
}
ret_code_t pdb_write_buf_get(pm_peer_id_t peer_id,
pm_peer_data_id_t data_id,
uint32_t n_bufs,
pm_peer_data_t * p_peer_data)
{
VERIFY_MODULE_INITIALIZED();
VERIFY_PARAM_NOT_NULL(p_peer_data);
VERIFY_DATA_ID_WRITE_BUF(data_id);
if ( (n_bufs == 0)
|| (n_bufs > N_WRITE_BUFFERS)
|| !pds_peer_id_is_allocated(peer_id))
{
return NRF_ERROR_INVALID_PARAM;
}
pdb_buffer_record_t * write_buffer_record;
uint8_t * p_buffer_memory;
bool new_record = false;
write_buffer_record = write_buffer_record_find(peer_id, data_id);
if ((write_buffer_record != NULL) && (write_buffer_record->n_bufs < n_bufs))
{
// @TODO: Copy?
// Existing buffer is too small.
for (uint8_t i = 0; i < write_buffer_record->n_bufs; i++)
{
pm_buffer_release(&m_pdb.write_buffer, write_buffer_record->buffer_block_id + i);
}
write_buffer_record_invalidate(write_buffer_record);
write_buffer_record = NULL;
}
else if ((write_buffer_record != NULL) && write_buffer_record->n_bufs > n_bufs)
{
// Release excess blocks.
for (uint8_t i = n_bufs; i < write_buffer_record->n_bufs; i++)
{
pm_buffer_release(&m_pdb.write_buffer, write_buffer_record->buffer_block_id + i);
}
}
if (write_buffer_record == NULL)
{
write_buffer_record_get(&write_buffer_record, peer_id, data_id);
if (write_buffer_record == NULL)
{
return NRF_ERROR_BUSY;
}
}
if (write_buffer_record->buffer_block_id == BUFFER_INVALID_ID)
{
write_buffer_record->buffer_block_id = pm_buffer_block_acquire(&m_pdb.write_buffer, n_bufs);
if (write_buffer_record->buffer_block_id == BUFFER_INVALID_ID)
{
write_buffer_record_invalidate(write_buffer_record);
return NRF_ERROR_BUSY;
}
new_record = true;
}
write_buffer_record->n_bufs = n_bufs;
p_buffer_memory = pm_buffer_ptr_get(&m_pdb.write_buffer, write_buffer_record->buffer_block_id);
if (p_buffer_memory == NULL)
{
return NRF_ERROR_INTERNAL;
}
peer_data_point_to_buffer(p_peer_data, data_id, p_buffer_memory, n_bufs);
if (new_record && (data_id == PM_PEER_DATA_ID_GATT_LOCAL))
{
p_peer_data->p_local_gatt_db->len = PM_LOCAL_DB_LEN(p_peer_data->length_words);
}
return NRF_SUCCESS;
}
ret_code_t pdb_write_buf_release(pm_peer_id_t peer_id, pm_peer_data_id_t data_id)
{
VERIFY_MODULE_INITIALIZED();
ret_code_t err_code = NRF_SUCCESS;
pdb_buffer_record_t * p_write_buffer_record;
p_write_buffer_record = write_buffer_record_find(peer_id, data_id);
if (p_write_buffer_record == NULL)
{
return NRF_ERROR_NOT_FOUND;
}
if (p_write_buffer_record->prepare_token != PDS_PREPARE_TOKEN_INVALID)
{
err_code = pds_peer_data_write_prepare_cancel(p_write_buffer_record->prepare_token);
if (err_code != NRF_SUCCESS)
{
err_code = NRF_ERROR_INTERNAL;
}
}
write_buffer_record_release(p_write_buffer_record);
return err_code;
}
ret_code_t pdb_write_buf_store_prepare(pm_peer_id_t peer_id, pm_peer_data_id_t data_id)
{
VERIFY_MODULE_INITIALIZED();
VERIFY_DATA_ID_WRITE_BUF(data_id);
ret_code_t err_code = NRF_SUCCESS;
pdb_buffer_record_t * p_write_buffer_record;
p_write_buffer_record = write_buffer_record_find(peer_id, data_id);
if (p_write_buffer_record == NULL)
{
return NRF_ERROR_NOT_FOUND;
}
if (p_write_buffer_record->prepare_token == PDS_PREPARE_TOKEN_INVALID)
{
uint8_t * p_buffer_memory = pm_buffer_ptr_get(&m_pdb.write_buffer, p_write_buffer_record->buffer_block_id);
pm_peer_data_const_t peer_data = {.data_id = data_id};
if (p_buffer_memory == NULL)
{
return NRF_ERROR_INTERNAL;
}
peer_data_const_point_to_buffer(&peer_data, data_id, p_buffer_memory, p_write_buffer_record->n_bufs);
write_buf_length_words_set(&peer_data);
err_code = pds_peer_data_write_prepare(&peer_data, &p_write_buffer_record->prepare_token);
if (err_code == NRF_ERROR_INVALID_LENGTH)
{
return NRF_ERROR_INTERNAL;
}
}
return err_code;
}
static ret_code_t write_or_update(pm_peer_id_t peer_id,
pm_peer_data_id_t data_id,
pm_peer_data_const_t * p_peer_data,
pm_store_token_t * p_store_token,
pm_prepare_token_t prepare_token)
{
pm_peer_data_flash_t old_peer_data;
pm_store_token_t old_store_token;
ret_code_t err_code = pds_peer_data_read_ptr_get(peer_id, data_id, &old_peer_data, &old_store_token);
if (err_code == NRF_SUCCESS)
{
err_code = pds_peer_data_write_prepare_cancel(prepare_token);
if ((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NULL))
{
err_code = pds_peer_data_update(peer_id, p_peer_data, old_store_token, p_store_token);
}
else
{
err_code = NRF_ERROR_INTERNAL;
}
}
else if (err_code == NRF_ERROR_NOT_FOUND)
{
if (prepare_token == PDS_PREPARE_TOKEN_INVALID)
{
err_code = pds_peer_data_write(peer_id, p_peer_data, p_store_token);
}
else
{
err_code = pds_peer_data_write_prepared(peer_id, p_peer_data, prepare_token, p_store_token);
}
}
return err_code;
}
ret_code_t pdb_write_buf_store(pm_peer_id_t peer_id,
pm_peer_data_id_t data_id)
{
VERIFY_MODULE_INITIALIZED();
VERIFY_DATA_ID_WRITE_BUF(data_id);
ret_code_t err_code = NRF_SUCCESS;
pdb_buffer_record_t * p_write_buffer_record;
uint8_t * p_buffer_memory;
pm_peer_data_const_t peer_data = {.data_id = data_id};
p_write_buffer_record = write_buffer_record_find(peer_id, data_id);
if (p_write_buffer_record == NULL)
{
return NRF_ERROR_NOT_FOUND;
}
if (p_write_buffer_record->store_requested)
{
return NRF_SUCCESS;
}
p_buffer_memory = pm_buffer_ptr_get(&m_pdb.write_buffer, p_write_buffer_record->buffer_block_id);
if (p_buffer_memory == NULL)
{
return NRF_ERROR_INTERNAL;
}
peer_data_const_point_to_buffer(&peer_data, data_id, p_buffer_memory, p_write_buffer_record->n_bufs);
write_buf_length_words_set(&peer_data);
err_code = write_or_update(peer_id, data_id, &peer_data, &p_write_buffer_record->store_token, p_write_buffer_record->prepare_token);
if (p_write_buffer_record->store_busy && p_write_buffer_record->store_flash_full)
{
m_pdb.n_writes--;
}
if (err_code == NRF_SUCCESS)
{
p_write_buffer_record->store_requested = true;
p_write_buffer_record->store_busy = false;
p_write_buffer_record->store_flash_full = false;
}
else
{
if (err_code == NRF_ERROR_BUSY)
{
m_pdb.n_writes++;
p_write_buffer_record->store_busy = true;
p_write_buffer_record->store_flash_full = false;
err_code = NRF_SUCCESS;
}
else if (err_code == NRF_ERROR_NO_MEM)
{
m_pdb.n_writes++;
p_write_buffer_record->store_busy = false;
p_write_buffer_record->store_flash_full = true;
}
else if ((err_code != NRF_ERROR_NO_MEM) && (err_code != NRF_ERROR_INVALID_PARAM))
{
err_code = NRF_ERROR_INTERNAL;
}
}
return err_code;
}
ret_code_t pdb_clear(pm_peer_id_t peer_id, pm_peer_data_id_t data_id)
{
VERIFY_MODULE_INITIALIZED();
return pds_peer_data_clear(peer_id, data_id);
}
uint32_t pdb_n_peers(void)
{
if (!MODULE_INITIALIZED)
{
return 0;
}
return pds_n_peers();
}
pm_peer_id_t pdb_next_peer_id_get(pm_peer_id_t prev_peer_id)
{
if (!MODULE_INITIALIZED)
{
return PM_PEER_ID_INVALID;
}
return pds_next_peer_id_get(prev_peer_id);
}
ret_code_t pdb_raw_read(pm_peer_id_t peer_id,
pm_peer_data_id_t data_id,
pm_peer_data_t * p_peer_data)
{
VERIFY_MODULE_INITIALIZED();
return pds_peer_data_read(peer_id, data_id, p_peer_data, &p_peer_data->length_words);
}
ret_code_t pdb_raw_store(pm_peer_id_t peer_id,
pm_peer_data_const_t * p_peer_data,
pm_store_token_t * p_store_token)
{
VERIFY_MODULE_INITIALIZED();
return write_or_update(peer_id, p_peer_data->data_id, p_peer_data, p_store_token, PDS_PREPARE_TOKEN_INVALID);
}

View File

@ -1,385 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 PEER_DATABASE_H__
#define PEER_DATABASE_H__
#include <stdint.h>
#include "peer_manager_types.h"
#include "peer_manager_internal.h"
#include "sdk_errors.h"
/**
* @cond NO_DOXYGEN
* @defgroup peer_database Peer Database
* @ingroup peer_manager
* @{
* @brief An internal module of @ref peer_manager. A module for simple management of reading and
* writing of peer data into persistent storage.
*
*/
#define PDB_WRITE_BUF_SIZE (sizeof(pm_peer_data_bonding_t))
/**@brief Events that can come from the peer_database module.
*/
typedef enum
{
PDB_EVT_WRITE_BUF_STORED, /**< A @ref pdb_write_buf_store operation has completed successfully. */
PDB_EVT_RAW_STORED, /**< A @ref pdb_raw_store operation has completed successfully. */
PDB_EVT_RAW_STORE_FAILED, /**< A @ref pdb_raw_store operation has failed. */
PDB_EVT_CLEARED, /**< A @ref pdb_clear operation has completed successfully. */
PDB_EVT_CLEAR_FAILED, /**< A @ref pdb_clear operation has failed. */
PDB_EVT_PEER_FREED, /**< A @ref pdb_peer_free operation has completed successfully. All associated data has been erased. */
PDB_EVT_PEER_FREE_FAILED, /**< A @ref pdb_peer_free operation has failed. */
PDB_EVT_COMPRESSED, /**< A compress procedure has completed. */
PDB_EVT_ERROR_NO_MEM, /**< An operation is blocked because the flash is full. It will be reattempted automatically after the next compress procedure. */
PDB_EVT_ERROR_UNEXPECTED, /**< An unexpected error occurred. This is a fatal error. */
} pdb_evt_id_t;
/**@brief Events that can come from the peer_database module.
*/
typedef struct
{
pdb_evt_id_t evt_id; /**< The event that has happened. */
pm_peer_id_t peer_id; /**< The id of the peer the event pertains to. */
pm_peer_data_id_t data_id; /**< The data the event pertains to. */
union
{
struct
{
bool update; /**< If true, an existing value was overwritten. */
} write_buf_stored_evt; /**< Additional information pertaining to the @ref PDB_EVT_WRITE_BUF_STORED event. */
struct
{
pm_store_token_t store_token; /**< A token identifying the store operation this event pertains to. */
} raw_stored_evt; /**< Additional information pertaining to the @ref PDB_EVT_RAW_STORED event. */
struct
{
pm_store_token_t store_token; /**< A token identifying the store operation this event pertains to. */
ret_code_t err_code; /**< Error code specifying what went wrong. */
} error_raw_store_evt; /**< Additional information pertaining to the @ref PDB_EVT_RAW_STORE_FAILED event. */
struct
{
ret_code_t err_code; /**< The error that occurred. */
} clear_failed_evt; /**< Additional information pertaining to the @ref PDB_EVT_CLEAR_FAILED event. */
struct
{
ret_code_t err_code; /**< The error that occurred. */
} peer_free_failed_evt; /**< Additional information pertaining to the @ref PDB_EVT_PEER_FREE_FAILED event. */
struct
{
ret_code_t err_code; /**< The unexpected error that occurred. */
} error_unexpected; /**< Additional information pertaining to the @ref PDB_EVT_ERROR_UNEXPECTED event. */
} params;
} pdb_evt_t;
/**@brief Event handler for events from the peer_data_storage module.
*
* @param[in] p_event The event that has happened.
*/
typedef void (*pdb_evt_handler_t)(pdb_evt_t const * p_event);
/**@brief Function for registering for events from the peer database.
*
* @note This function will initialize the module if it is not already initialized.
*
* @param[in] evt_handler Event handler to register.
*
* @retval NRF_SUCCESS Registration successful.
* @retval NRF_ERROR_NO_MEM No more event handlers can be registered.
* @retval NRF_ERROR_NULL evt_handler was NULL.
* @retval NRF_ERROR_INTERNAL An unexpected error happened.
*/
ret_code_t pdb_register(pdb_evt_handler_t evt_handler);
/**@brief Function for allocating persistent bond storage for a peer.
*
* @return The ID of the newly allocated storage.
* @retval PM_PEER_ID_INVALID If no peer ID is available.
*/
pm_peer_id_t pdb_peer_allocate(void);
/**@brief Function for freeing a peer's persistent bond storage.
*
* @note This function will call @ref pdb_write_buf_release on the data for this peer.
*
* @param[in] peer_id ID to be freed.
*
* @retval NRF_SUCCESS Peer ID was released and clear operation was initiated successfully.
* @retval NRF_ERROR_INVALID_PARAM Peer ID was invalid.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t pdb_peer_free(pm_peer_id_t peer_id);
/**@brief Function for retrieving pointers to read-only peer data.
*
* @note Reading this pointer is not safe in the strictest sense. If a safe read is required:
* - Disable interrupts
* - Call this function. If the return code is @ref NRF_SUCCESS, the following read is safe.
* - Read memory.
* - Enable interrupts.
* @note This buffer does not need to be released. It is a pointer directly to flash.
*
* @param[in] peer_id ID of peer to retrieve data for.
* @param[in] data_id Which piece of data to get.
* @param[out] p_peer_data Pointer to immutable peer data.
* @param[out] p_token Token that can be used to lock data in flash and check data validity.
*
* @retval NRF_SUCCESS Data retrieved successfully.
* @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated.
* @retval NRF_ERROR_NULL p_peer_data was NULL.
* @retval NRF_ERROR_NOT_FOUND This data was not found for this peer ID.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t pdb_read_buf_get(pm_peer_id_t peer_id,
pm_peer_data_id_t data_id,
pm_peer_data_flash_t * p_peer_data,
pm_store_token_t * p_token);
/**@brief Function for retrieving pointers to a write buffer for peer data.
*
* @details This function will provide pointers to a buffer of the data. The data buffer will not be
* written to persistent storage until @ref pdb_write_buf_store is called. The buffer is
* released by calling either @ref pdb_write_buf_release, @ref pdb_write_buf_store, or
* @ref pdb_peer_free.
*
* When the data_id refers to a variable length data type, the available size is written
* to the data, both the top-level, and any internal length fields.
*
* @note Calling this function on a peer_id/data_id pair that already has a buffer created will
* give the same buffer, not create a new one. If n_bufs was increased since last time, the
* buffer might be relocated to be able to provide additional room. In this case, the data
* will be copied. If n_bufs was increased since last time, this function might return @ref
* NRF_ERROR_BUSY. In that case, the buffer is automatically released.
*
* @param[in] peer_id ID of peer to get a write buffer for.
* @param[in] data_id Which piece of data to get.
* @param[in] n_bufs The number of contiguous buffers needed.
* @param[out] p_peer_data Pointers to mutable peer data.
*
* @retval NRF_SUCCESS Data retrieved successfully.
* @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated, or n_bufs was 0
* or more than the total available buffers.
* @retval NRF_ERROR_NULL p_peer_data was NULL.
* @retval NRF_ERROR_BUSY Not enough buffer(s) available.
* @retval NRF_ERROR_INTERNAL Unexpected internal error.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t pdb_write_buf_get(pm_peer_id_t peer_id,
pm_peer_data_id_t data_id,
uint32_t n_bufs,
pm_peer_data_t * p_peer_data);
/**@brief Function for freeing a write buffer allocated with @ref pdb_write_buf_get.
*
* @note This function will not write peer data to persistent memory. Data in released buffer will
* be lost.
*
* @note This function will undo any previous call to @ref pdb_write_buf_store_prepare for this
* piece of data.
*
* @param[in] peer_id ID of peer to release buffer for.
* @param[in] data_id Which piece of data to release buffer for.
*
* @retval NRF_SUCCESS Successfully released buffer.
* @retval NRF_ERROR_NOT_FOUND No buffer was allocated for this peer ID/data ID pair.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
* @retval NRF_ERROR_INTERNAL Unexpected internal error.
*/
ret_code_t pdb_write_buf_release(pm_peer_id_t peer_id, pm_peer_data_id_t data_id);
/**@brief Function for reserving space in persistent storage for data in a buffer.
*
* @note This function only works for data which has a write buffer allocated. If the write buffer
* is released, this prepare is undone.
*
* @note If space has already been reserved for this data, nothing is done.
*
* @param[in] peer_id The peer whose data to reserve space for.
* @param[in] data_id The type of data to reserve space for.
*
* @retval NRF_SUCCESS Successfully reserved space in persistent storage.
* @retval NRF_ERROR_NO_MEM Not enough room in persistent storage.
* @retval NRF_ERROR_BUSY Could not process request at this time. Reattempt later.
* @retval NRF_ERROR_NOT_FOUND No buffer has been allocated for this peer ID/data ID pair.
* @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t pdb_write_buf_store_prepare(pm_peer_id_t peer_id, pm_peer_data_id_t data_id);
/**@brief Function for writing data into persistent storage. Writing happens asynchronously.
*
* @note This will unlock the data after it has been written.
*
* @param[in] peer_id ID of peer to store data for.
* @param[in] data_id Which piece of data to store.
*
* @retval NRF_SUCCESS Data storing was successfully started.
* @retval NRF_ERROR_NO_MEM No space available in persistent storage. Please clear some
* space, the operation will be reattempted after the next compress
* procedure. This error will not happen if
* @ref pdb_write_buf_store_prepare is called beforehand.
* @retval NRF_ERROR_INVALID_PARAM Data ID was invalid.
* @retval NRF_ERROR_NOT_FOUND No buffer has been allocated for this peer ID/data ID pair.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
* @retval NRF_ERROR_INTERNAL Unexpected internal error.
*/
ret_code_t pdb_write_buf_store(pm_peer_id_t peer_id,
pm_peer_data_id_t data_id);
/**@brief Function for clearing data from persistent storage.
*
* @param[in] peer_id ID of peer to clear data for.
* @param[in] data_id Which piece of data to clear.
*
* @retval NRF_SUCCESS The clear was initiated successfully.
* @retval NRF_ERROR_INVALID_PARAM Data ID or peer ID was invalid.
* @retval NRF_ERROR_NOT_FOUND Nothing to clear for this peer ID/data ID combination.
* @retval NRF_ERROR_BUSY Underlying modules are busy and can't take any more requests at
* this moment.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
* @retval NRF_ERROR_INTERNAL Internal error.
*/
ret_code_t pdb_clear(pm_peer_id_t peer_id, pm_peer_data_id_t data_id);
/**@brief Function for querying the number of valid peer IDs available. I.E the number of peers
* in persistent storage.
*
* @return The number of valid peer IDs.
*/
uint32_t pdb_n_peers(void);
/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. Can be
* used to loop through all used peer IDs.
*
* @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary
* peer ID.
*
* @param[in] prev_peer_id The previous peer ID.
*
* @return The next peer ID.
* @return The first ordinary peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID.
* @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID.
*/
pm_peer_id_t pdb_next_peer_id_get(pm_peer_id_t prev_peer_id);
/**@brief Function for updating currently stored peer data to a new version
*
* @details Updating happens asynchronously.
* Expect a @ref PDS_EVT_STORED or @ref PDS_EVT_ERROR_STORE for the store token
* and a @ref PDS_EVT_ERROR_CLEAR or @ref PDS_EVT_ERROR_CLEAR for the old token
*
* @param[in] peer_data New data
* @param[in] old_token Store token for the old data
* @param[out] p_store_token Store token for the new data
*
* @retval NRF_SUCESS The update was initiated successfully
* @retval NRF_ERROR_NOT_FOUND The old store token was invalid.
* @retval NRF_ERROR_NULL Data contained a NULL pointer.
* @retval NRF_ERROR_NO_MEM No space available in persistent storage.
* @retval NRF_ERROR_BUSY FDS or underlying modules are busy and can't take any
* more requests
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t pdb_peer_data_update(pm_peer_data_const_t peer_data,
pm_store_token_t old_token,
pm_store_token_t * p_store_token);
/**@brief Function for reading data directly from persistent storage to external memory.
*
* @param[in] peer_id ID of peer to read data for.
* @param[in] data_id Which piece of data to read.
* @param[inout] p_peer_data Where to store the data. If the data to be read has variable length,
* the appropriate length field needs to reflect the available buffer
* space. On a successful read, the length field is updated to match the
* length of the read data.
*
* @retval NRF_SUCCESS Data successfully read.
* @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated.
* @retval NRF_ERROR_NULL p_peer_data contained a NULL pointer.
* @retval NRF_ERROR_NOT_FOUND This data was not found for this peer ID.
* @retval NRF_ERROR_DATA_SIZE The provided buffer was not large enough.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t pdb_raw_read(pm_peer_id_t peer_id,
pm_peer_data_id_t data_id,
pm_peer_data_t * p_peer_data);
/**@brief Function for writing data directly to persistent storage from external memory.
*
* @param[in] peer_id ID of peer to write data for.
* @param[in] p_peer_data Data to store.
* @param[out] p_store_token A token identifying this particular store operation. The token can be
* used to identify events pertaining to this operation.
*
* @retval NRF_SUCCESS Data successfully written.
* @retval NRF_ERROR_INVALID_PARAM Data ID or Peer ID was invalid or unallocated.
* @retval NRF_ERROR_NULL p_peer_data contained a NULL pointer.
* @retval NRF_ERROR_NO_MEM No space available in persistent storage.
* @retval NRF_ERROR_INVALID_LENGTH Data length above the maximum allowed.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
* @retval NRF_ERROR_BUSY Unable to perform operation at this time.
*/
ret_code_t pdb_raw_store(pm_peer_id_t peer_id,
pm_peer_data_const_t * p_peer_data,
pm_store_token_t * p_store_token);
/** @}
* @endcond
*/
#endif /* PEER_DATABASE_H__ */

View File

@ -1,186 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "peer_id.h"
#include <stdint.h>
#include <string.h>
#include "sdk_errors.h"
#include "peer_manager_types.h"
#include "pm_mutex.h"
typedef struct
{
uint8_t active_peer_ids[MUTEX_STORAGE_SIZE(PM_PEER_ID_N_AVAILABLE_IDS)]; /**< Bitmap designating which peer IDs are in use. */
uint8_t deleted_peer_ids[MUTEX_STORAGE_SIZE(PM_PEER_ID_N_AVAILABLE_IDS)]; /**< Bitmap designating which peer IDs are marked for deletion. */
} pi_t;
static pi_t m_pi = {{0}, {0}};
static void internal_state_reset(pi_t * p_pi)
{
memset(p_pi, 0, sizeof(pi_t));
}
void peer_id_init(void)
{
internal_state_reset(&m_pi);
pm_mutex_init(m_pi.active_peer_ids, PM_PEER_ID_N_AVAILABLE_IDS);
pm_mutex_init(m_pi.deleted_peer_ids, PM_PEER_ID_N_AVAILABLE_IDS);
}
static pm_peer_id_t claim(pm_peer_id_t peer_id, uint8_t * mutex_group)
{
pm_peer_id_t allocated_peer_id = PM_PEER_ID_INVALID;
if (peer_id == PM_PEER_ID_INVALID)
{
allocated_peer_id = pm_mutex_lock_first_available(mutex_group, PM_PEER_ID_N_AVAILABLE_IDS);
if (allocated_peer_id == PM_PEER_ID_N_AVAILABLE_IDS)
{
allocated_peer_id = PM_PEER_ID_INVALID;
}
}
else if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS)
{
bool lock_success = pm_mutex_lock(mutex_group, peer_id);
allocated_peer_id = lock_success ? peer_id : PM_PEER_ID_INVALID;
}
return allocated_peer_id;
}
static void release(pm_peer_id_t peer_id, uint8_t * mutex_group)
{
if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS)
{
pm_mutex_unlock(mutex_group, peer_id);
}
}
pm_peer_id_t peer_id_allocate(pm_peer_id_t peer_id)
{
return claim(peer_id, m_pi.active_peer_ids);
}
bool peer_id_delete(pm_peer_id_t peer_id)
{
if (peer_id == PM_PEER_ID_INVALID)
{
return false;
}
pm_peer_id_t deleted_id = claim(peer_id, m_pi.deleted_peer_ids);
return (deleted_id == peer_id);
}
void peer_id_free(pm_peer_id_t peer_id)
{
release(peer_id, m_pi.active_peer_ids);
release(peer_id, m_pi.deleted_peer_ids);
}
bool peer_id_is_allocated(pm_peer_id_t peer_id)
{
if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS)
{
return pm_mutex_lock_status_get(m_pi.active_peer_ids, peer_id);
}
return false;
}
bool peer_id_is_deleted(pm_peer_id_t peer_id)
{
if (peer_id < PM_PEER_ID_N_AVAILABLE_IDS)
{
return pm_mutex_lock_status_get(m_pi.deleted_peer_ids, peer_id);
}
return false;
}
pm_peer_id_t next_id_get(pm_peer_id_t prev_peer_id, uint8_t * mutex_group)
{
pm_peer_id_t i = (prev_peer_id == PM_PEER_ID_INVALID) ? 0 : (prev_peer_id + 1);
for (; i < PM_PEER_ID_N_AVAILABLE_IDS; i++)
{
if (pm_mutex_lock_status_get(mutex_group, i))
{
return i;
}
}
return PM_PEER_ID_INVALID;
}
pm_peer_id_t peer_id_get_next_used(pm_peer_id_t prev_peer_id)
{
return next_id_get(prev_peer_id, m_pi.active_peer_ids);
}
pm_peer_id_t peer_id_get_next_deleted(pm_peer_id_t prev_peer_id)
{
return next_id_get(prev_peer_id, m_pi.deleted_peer_ids);
}
uint32_t peer_id_n_ids(void)
{
uint32_t n_ids = 0;
for (pm_peer_id_t i = 0; i < PM_PEER_ID_N_AVAILABLE_IDS; i++)
{
n_ids += pm_mutex_lock_status_get(m_pi.active_peer_ids, i);
}
return n_ids;
}

View File

@ -1,159 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 PEER_ID_H__
#define PEER_ID_H__
#include <stdint.h>
#include "sdk_errors.h"
#include "nrf_ble_gap.h"
#include "peer_manager_types.h"
/**
* @cond NO_DOXYGEN
* @defgroup peer_id Peer IDs
* @ingroup peer_manager
* @{
* @brief An internal module of @ref peer_manager. This module keeps track of which peer IDs are in
* use and which are free.
*/
/**@brief Function for initializing the module.
*/
void peer_id_init(void);
/**@brief Function for claiming an unused peer ID.
*
* @param peer_id The peer ID to allocate. If this is @ref PM_PEER_ID_INVALID, the first available
* will be allocated.
*
* @return The allocated peer ID.
* @retval PM_PEER_ID_INVALID If no peer ID could be allocated or module is not initialized.
*/
pm_peer_id_t peer_id_allocate(pm_peer_id_t peer_id);
/**@brief Function for marking a peer ID for deletion.
*
* @param peer_id The peer ID to delete.
*
* @retval true Deletion was successful.
* @retval false Peer ID already marked for deletion, peer_id was PM_PEER_ID_INVALID, or module is
* not initialized.
*/
bool peer_id_delete(pm_peer_id_t peer_id);
/**@brief Function for freeing a peer ID and clearing all data associated with it in persistent
* storage.
*
* @param[in] peer_id Peer ID to free.
*/
void peer_id_free(pm_peer_id_t peer_id);
/**@brief Function for finding out whether a peer ID is marked for deletion.
*
* @param[in] peer_id The peer ID to inquire about.
*
* @retval true peer_id is in marked for deletion.
* @retval false peer_id is not marked for deletion, or the module is not initialized.
*/
bool peer_id_is_deleted(pm_peer_id_t peer_id);
/**@brief Function for finding out whether a peer ID is in use.
*
* @param[in] peer_id The peer ID to inquire about.
*
* @retval true peer_id is in use.
* @retval false peer_id is free, or the module is not initialized.
*/
bool peer_id_is_allocated(pm_peer_id_t peer_id);
/**@brief Function for getting the next peer ID in the sequence of all used peer IDs. Can be
* used to loop through all used peer IDs.
*
* @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary
* peer ID.
*
* @param[in] prev_peer_id The previous peer ID.
*
* @return The next peer ID.
* @return The first used peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID.
* @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID or the module is
* not initialized.
*/
pm_peer_id_t peer_id_get_next_used(pm_peer_id_t prev_peer_id);
/**@brief Function for getting the next peer ID in the sequence of all peer IDs marked for deletion.
* Can be used to loop through all peer IDs marked for deletion.
*
* @note @ref PM_PEER_ID_INVALID is considered to be before the first and after the last ordinary
* peer ID.
*
* @param[in] prev_peer_id The previous peer ID.
*
* @return The next peer ID.
* @return The first used peer ID if prev_peer_id was @ref PM_PEER_ID_INVALID.
* @retval PM_PEER_ID_INVALID if prev_peer_id was the last ordinary peer ID or the module is
* not initialized.
*/
pm_peer_id_t peer_id_get_next_deleted(pm_peer_id_t prev_peer_id);
/**@brief Function for querying the number of valid peer IDs available. I.E the number of peers
* in persistent storage.
*
* @return The number of valid peer IDs, or 0 if module is not initialized.
*/
uint32_t peer_id_n_ids(void);
/** @}
* @endcond
*/
#endif /* PEER_ID_H__ */

View File

@ -1,726 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 peer_manager.h
*
* @defgroup peer_manager Peer Manager
* @ingroup ble_sdk_lib
* @{
* @brief Module for managing BLE bonding, which includes controlling encryption and pairing
* procedures as well as persistently storing different pieces of data that must be stored
* when bonded.
*
* @details The API consists of functions for configuring the pairing and encryption behavior of the
* device and functions for manipulating the stored data.
*/
#ifndef PEER_MANAGER_H__
#define PEER_MANAGER_H__
#include <stdint.h>
#include <stdbool.h>
#include "sdk_common.h"
#include "nrf_ble.h"
#include "nrf_ble_gap.h"
#include "peer_manager_types.h"
#include "peer_database.h"
/**@brief Security status of a connection.
*/
typedef struct
{
uint8_t connected : 1; /**< @brief The connection is active (not disconnected). */
uint8_t encrypted : 1; /**< @brief Communication on this link is encrypted. */
uint8_t mitm_protected : 1; /**< @brief The encrypted communication is also protected against man-in-the-middle attacks. */
uint8_t bonded : 1; /**< @brief The peer is bonded with us. */
} pm_conn_sec_status_t;
/**@brief Types of events that can come from the @ref peer_manager module.
*/
typedef enum
{
PM_EVT_BONDED_PEER_CONNECTED, /**< @brief A connected peer has been identified as one with which we have a bond. When performing bonding with a peer for the first time, this event will not be sent until a new connection is established with the peer. When we are central, this event is always sent when the Peer Manager receives the @ref BLE_GAP_EVT_CONNECTED event. When we are peripheral, this event might in rare cases arrive later. */
PM_EVT_CONN_SEC_START, /**< @brief A security procedure has started on a link, initiated either locally or remotely. The security procedure is using the last parameters provided via @ref pm_sec_params_set. This event is always followed by either a @ref PM_EVT_CONN_SEC_SUCCEEDED or a @ref PM_EVT_CONN_SEC_FAILED event. This is an informational event; no action is needed for the procedure to proceed. */
PM_EVT_CONN_SEC_SUCCEEDED, /**< @brief A link has been encrypted, either as a result of a call to @ref pm_conn_secure or a result of an action by the peer. The event structure contains more information about the circumstances. This event might contain a peer ID with the value @ref PM_PEER_ID_INVALID, which means that the peer (central) used an address that could not be identified, but it used an encryption key (LTK) that is present in the database. */
PM_EVT_CONN_SEC_FAILED, /**< @brief A pairing or encryption procedure has failed. In some cases, this means that security is not possible on this link (temporarily or permanently). How to handle this error depends on the application. */
PM_EVT_CONN_SEC_CONFIG_REQ, /**< @brief The peer (central) has requested pairing, but a bond already exists with that peer. Reply by calling @ref pm_conn_sec_config_reply before the event handler returns. If no reply is sent, a default is used. */
PM_EVT_STORAGE_FULL, /**< @brief There is no more room for peer data in flash storage. To solve this problem, delete data that is not needed anymore and run a garbage collection procedure in FDS. */
PM_EVT_ERROR_UNEXPECTED, /**< @brief An unrecoverable error happened inside Peer Manager. An operation failed with the provided error. */
PM_EVT_PEER_DATA_UPDATE_SUCCEEDED, /**< @brief A piece of peer data was stored, updated, or cleared in flash storage. This event is sent for all successful changes to peer data, also those initiated internally in Peer Manager. To identify an operation, compare the store token in the event with the store token received during the initiating function call. Events from internally initiated changes might have invalid store tokens. */
PM_EVT_PEER_DATA_UPDATE_FAILED, /**< @brief A piece of peer data could not be stored, updated, or cleared in flash storage. This event is sent instead of @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED for the failed operation. */
PM_EVT_PEER_DELETE_SUCCEEDED, /**< @brief A peer was cleared from flash storage, for example because a call to @ref pm_peer_delete succeeded. This event can also be sent as part of a call to @ref pm_peers_delete or internal cleanup. */
PM_EVT_PEER_DELETE_FAILED, /**< @brief A peer could not be cleared from flash storage. This event is sent instead of @ref PM_EVT_PEER_DELETE_SUCCEEDED for the failed operation. */
PM_EVT_PEERS_DELETE_SUCCEEDED, /**< @brief A call to @ref pm_peers_delete has completed successfully. Flash storage now contains no peer data. */
PM_EVT_PEERS_DELETE_FAILED, /**< @brief A call to @ref pm_peers_delete has failed, which means that at least one of the peers could not be deleted. Other peers might have been deleted, or might still be queued to be deleted. No more @ref PM_EVT_PEERS_DELETE_SUCCEEDED or @ref PM_EVT_PEERS_DELETE_FAILED events are sent until the next time @ref pm_peers_delete is called. */
PM_EVT_LOCAL_DB_CACHE_APPLIED, /**< @brief Local database values for a peer (taken from flash storage) have been provided to the SoftDevice. */
PM_EVT_LOCAL_DB_CACHE_APPLY_FAILED, /**< @brief Local database values for a peer (taken from flash storage) were rejected by the SoftDevice, which means that either the database has changed or the user has manually set the local database to an invalid value (using @ref pm_peer_data_store). */
PM_EVT_SERVICE_CHANGED_IND_SENT, /**< @brief A service changed indication has been sent to a peer, as a result of a call to @ref pm_local_database_has_changed. This event will be followed by a @ref PM_EVT_SERVICE_CHANGED_IND_CONFIRMED event if the peer acknowledges the indication. */
PM_EVT_SERVICE_CHANGED_IND_CONFIRMED, /**< @brief A service changed indication that was sent has been confirmed by a peer. The peer can now be considered aware that the local database has changed. */
} pm_evt_id_t;
/**@brief Parameters specific to the @ref PM_EVT_CONN_SEC_SUCCEEDED event.
*/
typedef struct
{
pm_conn_sec_procedure_t procedure; /**< @brief The procedure that led to securing the link. */
} pm_conn_secured_evt_t;
/**@brief Parameters specific to the @ref PM_EVT_CONN_SEC_FAILED event.
*/
typedef struct
{
pm_conn_sec_procedure_t procedure; /**< @brief The procedure that failed. */
pm_sec_error_code_t error; /**< @brief An error code that describes the failure. */
uint8_t error_src; /**< @brief The party that raised the error, see @ref BLE_GAP_SEC_STATUS_SOURCES. */
} pm_conn_secure_failed_evt_t;
/**@brief Actions that can be performed to peer data in persistent storage.
*/
typedef enum
{
PM_PEER_DATA_OP_UPDATE, /**< @brief Writing or overwriting the data. */
PM_PEER_DATA_OP_DELETE, /**< @brief Removing the data. */
} pm_peer_data_op_t;
/**@brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED event.
*/
typedef struct
{
pm_peer_data_id_t data_id; /**< @brief The type of the data that was changed. */
pm_peer_data_op_t action; /**< @brief What happened to the data. */
uint8_t flash_changed : 1; /**< @brief If this is false, no operation was done in flash, because the value was already what it should be. Please note that in certain scenarios, this flag will be true even if the new value is the same as the old. */
pm_store_token_t token; /**< @brief Token that identifies the operation. For @ref PM_PEER_DATA_OP_DELETE actions, this token can be disregarded. For @ref PM_PEER_DATA_OP_UPDATE actions, compare this token with the token that is received from a call to a @ref PM_PEER_DATA_FUNCTIONS function. */
} pm_peer_data_update_succeeded_evt_t;
/**@brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_FAILED event.
*/
typedef struct
{
pm_peer_data_id_t data_id; /**< @brief The type of the data that was supposed to be changed. */
pm_peer_data_op_t action; /**< @brief The action that failed. */
pm_store_token_t token; /**< @brief Token that identifies the operation. For @ref PM_PEER_DATA_OP_DELETE actions, this token can be disregarded. For @ref PM_PEER_DATA_OP_UPDATE actions, compare this token with the token that is received from a call to a @ref PM_PEER_DATA_FUNCTIONS function. */
ret_code_t error; /**< @brief An error code that describes the failure. */
} pm_peer_data_update_failed_t;
/**@brief Standard parameters for failure events.
*/
typedef struct
{
ret_code_t error; /**< @brief The error that occurred. */
} pm_failure_evt_t;
/**@brief An event from the @ref peer_manager module.
*
* @details The structure contains both standard parameters and parameters that are specific to some events.
*/
typedef struct
{
pm_evt_id_t evt_id; /**< @brief The type of the event. */
uint16_t conn_handle; /**< @brief The connection that this event pertains to, or @ref BLE_CONN_HANDLE_INVALID. */
pm_peer_id_t peer_id; /**< @brief The bonded peer that this event pertains to, or @ref PM_PEER_ID_INVALID. */
union
{
pm_conn_secured_evt_t conn_sec_succeeded; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_SUCCEEDED event. */
pm_conn_secure_failed_evt_t conn_sec_failed; /**< @brief Parameters specific to the @ref PM_EVT_CONN_SEC_FAILED event. */
pm_peer_data_update_succeeded_evt_t peer_data_update_succeeded; /**< @brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED event. */
pm_peer_data_update_failed_t peer_data_update_failed; /**< @brief Parameters specific to the @ref PM_EVT_PEER_DATA_UPDATE_FAILED event. */
pm_failure_evt_t peer_delete_failed; /**< @brief Parameters specific to the @ref PM_EVT_PEER_DELETE_FAILED event. */
pm_failure_evt_t peers_delete_failed_evt; /**< @brief Parameters specific to the @ref PM_EVT_PEERS_DELETE_FAILED event. */
pm_failure_evt_t error_unexpected; /**< @brief Parameters specific to the @ref PM_EVT_PEER_DELETE_FAILED event. */
} params;
} pm_evt_t;
/**@brief Event handler for events from the @ref peer_manager module.
*
* @sa pm_register
*
* @param[in] p_event The event that has occurred.
*/
typedef void (*pm_evt_handler_t)(pm_evt_t const * p_event);
/**@brief Function for initializing the Peer Manager.
*
* @details You must initialize the Peer Manager before you can call any other Peer Manager
* functions.
*
* @retval NRF_SUCCESS If initialization was successful.
* @retval NRF_ERROR_INTERNAL If another error occurred.
*/
ret_code_t pm_init(void);
/**@brief Function for registering an event handler with the Peer Manager.
*
* @param[in] event_handler Callback for events from the @ref peer_manager module. @p event_handler
* is called for every event that the Peer Manager sends after this
* function is called.
*
* @retval NRF_SUCCESS If initialization was successful.
* @retval NRF_ERROR_NULL If @p event_handler was NULL.
* @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized.
*/
ret_code_t pm_register(pm_evt_handler_t event_handler);
/**@brief Function for providing pairing and bonding parameters to use for pairing procedures.
*
* @details Until this function is called, all bonding procedures that are initiated by the
* peer are rejected.
*
* This function can be called multiple times with different parameters, even with NULL as
* @p p_sec_params, in which case the Peer Manager starts rejecting all procedures again.
*
* @param[in] p_sec_params Security parameters to be used for subsequent security procedures.
*
* @retval NRF_SUCCESS If the parameters were set successfully.
* @retval NRF_ERROR_INVALID_PARAM If the combination of parameters is invalid.
* @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized.
* @retval NRF_ERROR_INTERNAL If another error occurred.
*/
ret_code_t pm_sec_params_set(ble_gap_sec_params_t * p_sec_params);
/**@brief Function for passing BLE events to the Peer Manager.
*
* @details For the module to work as expected, this function must be called with each BLE event
* from the SoftDevice. It must be called after @ref ble_conn_state_on_ble_evt, but before
* the application processes the event.
*
* Calling this function before @ref pm_init is safe, but without effect.
*
* @param[in] p_ble_evt BLE stack event that is dispatched to the function.
*/
void pm_on_ble_evt(ble_evt_t * p_ble_evt);
/**@brief Function for establishing encryption on a connection, and optionally establishing a bond.
*
* @details This function attempts to secure the link that is specified by @p conn_handle. It uses
* the parameters that were previously provided in a call to @ref pm_sec_params_set.
*
* If the connection is a master connection, calling this function starts a security
* procedure on the link. If we have keys from a previous bonding procedure with this peer
* and the keys meet the security requirements in the currently active sec_params, the
* function attempts to establish encryption with the existing keys. If no key exists, the
* function attempts to pair and bond according to the currently active sec_params.
*
* If the function completes successfully, a @ref PM_EVT_CONN_SEC_START event is sent.
* The procedure might be queued, in which case the @ref PM_EVT_CONN_SEC_START event is
* delayed until the procedure is initiated in the SoftDevice.
*
* If the connection is a slave connection, the function sends a security request to
* the peer (master). It is up to the peer then to initiate pairing or encryption.
* If the peer ignores the request, a @ref BLE_GAP_EVT_TIMEOUT event occurs
* with the source @ref BLE_GAP_TIMEOUT_SRC_SECURITY_REQUEST. Otherwise, the peer initiates
* security, in which case things happen as if the peer had initiated security itself.
* See @ref PM_EVT_CONN_SEC_START for information about peer-initiated security.
*
* @param[in] conn_handle Connection handle of the link as provided by the SoftDevice.
* @param[in] force_repairing Whether to force a pairing procedure even if there is an existing
* encryption key. This argument is relevant only for
* the central role. Recommended value: false.
*
* @retval NRF_SUCCESS If the operation completed successfully.
* @retval NRF_ERROR_TIMEOUT If there was an SMP time-out, so that no more SMP
* operations can be performed on this link.
* @retval BLE_ERROR_INVALID_CONN_HANDLE If the connection handle is invalid.
* @retval NRF_ERROR_NOT_FOUND If the security parameters have not been set.
* @retval NRF_ERROR_NO_MEM If there is no more space in flash.
* @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized, or the peer is
* disconnected or in the process of disconnecting.
* @retval NRF_ERROR_INTERNAL If another error occurred.
*/
ret_code_t pm_conn_secure(uint16_t conn_handle, bool force_repairing);
/**@brief Function for providing security configuration for a link.
*
* @details This function is optional, and must be called in reply to a @ref
* PM_EVT_CONN_SEC_CONFIG_REQ event, before the Peer Manager event handler returns. If it
* is not called in time, a default configuration is used. See @ref pm_conn_sec_config_t
* for the value of the default.
*
* @param[in] conn_handle The connection to set the configuration for.
* @param[in] p_conn_sec_config The configuration.
*/
void pm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config);
/**@brief Function for manually informing that the local database has changed.
*
* @details This function sends a service changed indication to all bonded and/or connected peers
* that subscribe to this indication. If a bonded peer is not connected, the indication is
* sent when it reconnects. Every time an indication is sent, a @ref
* PM_EVT_SERVICE_CHANGED_IND_SENT event occurs, followed by a @ref
* PM_EVT_SERVICE_CHANGED_IND_CONFIRMED when the peer sends its confirmation. Peers that
* are not subscribed to the service changed indication when this function is called do not
* receive an indication, and no events are sent to the user. Likewise, if the service
* changed characteristic is not present in the local database, this no indications are
* sent peers, and no events are sent to the user.
*/
void pm_local_database_has_changed(void);
/**@brief Function for getting the security status of a connection.
*
* @param[in] conn_handle Connection handle of the link as provided by the SoftDevice.
* @param[out] p_conn_sec_status Security status of the link.
*
* @retval NRF_SUCCESS If pairing was initiated successfully.
* @retval BLE_ERROR_INVALID_CONN_HANDLE If the connection handle is invalid.
* @retval NRF_ERROR_NULL If @p p_conn_sec_status was NULL.
* @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized.
*/
ret_code_t pm_conn_sec_status_get(uint16_t conn_handle, pm_conn_sec_status_t * p_conn_sec_status);
/**@brief Experimental function for specifying the public key to use for LESC operations.
*
* @details This function can be called multiple times. The specified public key will be used for
* all subsequent LESC (LE Secure Connections) operations until the next time this function
* is called.
*
* @note The key must continue to reside in application memory as it is not copied by Peer Manager.
*
* @param[in] p_public_key The public key to use for all subsequent LESC operations.
*
* @retval NRF_SUCCESS Pairing initiated successfully.
* @retval NRF_ERROR_INVALID_STATE Peer Manager is not initialized.
*/
ret_code_t pm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key);
/**
* @brief Function for constructing a whitelist for use when advertising.
*
* @details This function constructs a whitelist that contains the addresses and IRKs of the
* provided peer IDs. If @p p_peer_ids is NULL, the first (lowest) 8 peer IDs are chosen.
* If @ref ble_gap_whitelist_t.pp_addrs in @p p_whitelist is NULL, the whitelist contains
* only IRKs, and vice versa.
*
* @note When using a whitelist, always use the whitelist that was created or set by the most recent
* call to this function or to @ref pm_whitelist_custom.
* @note Do not call this function while advertising or scanning with another whitelist.
*
* @param[in] p_peer_ids The IDs of the peers to be added to the whitelist, or NULL.
* @param[in] n_peer_ids The number of peer IDs in @p p_peer_ids.
* @param[in,out] p_whitelist The constructed whitelist. Note that @p p_whitelist->pp_addrs
* must be NULL or point to an array with size @ref
* BLE_GAP_WHITELIST_ADDR_MAX_COUNT and @p p_whitelist->pp_irks
* must be NULL or point to an array with size @ref
* BLE_GAP_WHITELIST_IRK_MAX_COUNT.
*
* @retval NRF_SUCCESS If the whitelist was created successfully.
* @retval NRF_ERROR_NULL If @p p_whitelist was NULL.
* @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized.
*/
ret_code_t pm_whitelist_create(pm_peer_id_t * p_peer_ids,
uint8_t n_peer_ids,
ble_gap_whitelist_t * p_whitelist);
/**
* @brief Function for informing the Peer Manager of what whitelist should be used.
*
* @details This function should be used if the application wants to use a whitelist that is
* created in the application. When using Peer Manager, this function must be called to
* inform that the custom whitelist should be used instead of the one in Peer Manager.
*
* @note When using a whitelist, always use the whitelist that was created or set by the most recent
* call to this function or to @ref pm_whitelist_create.
* @note Do not call this function while advertising or scanning with another whitelist.
* @note Do not add any IRKs to the whitelist that are not present in the Peer Manager's persistent
* storage.
*
* @param[in] p_whitelist The whitelist.
*
* @retval NRF_SUCCESS If the operation completed successfully.
* @retval NRF_ERROR_NULL If @p p_whitelist was NULL.
* @retval NRF_ERROR_NOT_FOUND If one or more of the whitelist's IRKs was not found in the Peer
* Manager's persistent storage.
* @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized.
*/
ret_code_t pm_whitelist_custom(ble_gap_whitelist_t * p_whitelist);
/**
* @brief Function for getting the connection handle of the connection with a bonded peer.
*
* @param[in] peer_id The peer ID of the bonded peer.
* @param[out] p_conn_handle Connection handle, or @ref BLE_ERROR_INVALID_CONN_HANDLE if the peer
* is not connected.
*
* @retval NRF_SUCCESS If the connection handle was determined successfully.
* @retval NRF_ERROR_NULL If @p p_conn_handle was NULL.
* @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized.
*/
ret_code_t pm_conn_handle_get(pm_peer_id_t peer_id, uint16_t * p_conn_handle);
/**@brief Function for getting the peer ID of a connected peer.
*
* @param[in] conn_handle Connection handle.
* @param[out] p_peer_id Peer ID, or @ref PM_PEER_ID_INVALID if the peer is not bonded or
* @p conn_handle does not refer to a connection.
*
* @retval NRF_SUCCESS If the peer ID was retrieved successfully.
* @retval NRF_ERROR_NULL If @p p_peer_id was NULL.
* @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized.
*/
ret_code_t pm_peer_id_get(uint16_t conn_handle, pm_peer_id_t * p_peer_id);
/**@brief Function for getting the next peer ID in the sequence of all used peer IDs.
*
* @details This function can be used to loop through all used peer IDs. The order in which
* peer IDs are returned should be considered unpredictable. @ref PM_PEER_ID_INVALID
* is considered to be before the first and after the last used peer ID.
*
* @details To loop through all peer IDs exactly once, use the following constuct:
* @code{c}
* pm_peer_id_t current_peer_id = pm_next_peer_id_get(PM_PEER_ID_INVALID);
* while (current_peer_id != PM_PEER_ID_INVALID)
* {
* // Do something with current_peer_id.
* current_peer_id = pm_next_peer_id_get(current_peer_id)
* }
* @endcode
*
* @param[in] prev_peer_id The previous peer ID.
*
* @return The next peer ID. If @p prev_peer_id was @ref PM_PEER_ID_INVALID, the
* next peer ID is the first used peer ID. If @p prev_peer_id was the last
* used peer ID, the function returns @ref PM_PEER_ID_INVALID.
*/
pm_peer_id_t pm_next_peer_id_get(pm_peer_id_t prev_peer_id);
/**@brief Function for querying the number of valid peer IDs that are available.
*
* @details This function returns the number of peers for which there is data in persistent storage.
*
* @return The number of valid peer IDs.
*/
uint32_t pm_peer_count(void);
/**@anchor PM_PEER_DATA_FUNCTIONS
* @name Functions (Peer Data)
* Functions for manipulating peer data.
* @{
*/
/**
* @{
*/
/**@brief Function for retrieving stored data of a peer.
*
* @note The length of the provided buffer must be a multiple of 4.
*
* @param[in] peer_id Peer ID to get data for.
* @param[in] data_id Which type of data to read.
* @param[out] p_data Where to put the retrieved data.
* @param[inout] p_len In: The length in bytes of @p p_data.
* Out: The length in bytes of the read data, if the read was successful.
*
* @retval NRF_SUCCESS If the data was read successfully.
* @retval NRF_ERROR_INVALID_PARAM If the the data type or the peer ID was invalid or unallocated,
* or if the length in @p p_length was not a multiple of 4.
* @retval NRF_ERROR_NULL If a pointer parameter was NULL.
* @retval NRF_ERROR_NOT_FOUND If no stored data was found for this peer ID/data ID combination.
* @retval NRF_ERROR_DATA_SIZE If the provided buffer was not large enough.
* @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized.
*/
ret_code_t pm_peer_data_load(pm_peer_id_t peer_id,
pm_peer_data_id_t data_id,
void * p_data,
uint16_t * p_len);
/**@brief Function for reading a peer's bonding data (@ref PM_PEER_DATA_ID_BONDING).
* @details See @ref pm_peer_data_load for parameters and return values. */
ret_code_t pm_peer_data_bonding_load(pm_peer_id_t peer_id,
pm_peer_data_bonding_t * p_data);
/**@brief Function for reading a peer's remote DB values. (@ref PM_PEER_DATA_ID_GATT_REMOTE).
* @details See @ref pm_peer_data_load for parameters and return values. */
ret_code_t pm_peer_data_remote_db_load(pm_peer_id_t peer_id,
ble_gatt_db_srv_t * p_data,
uint16_t * p_len);
/**@brief Function for reading a peer's application data. (@ref PM_PEER_DATA_ID_APPLICATION).
* @details See @ref pm_peer_data_load for parameters and return values. */
ret_code_t pm_peer_data_app_data_load(pm_peer_id_t peer_id,
uint8_t * p_data,
uint16_t * p_len);
/** @}*/
/**
* @{
*/
/**@brief Function for setting or updating stored data of a peer.
*
* @note Writing the data to persistent storage happens asynchronously. Therefore, the buffer
* that contains the data must be kept alive until the operation has completed.
*
* @note The data written using this function may later be overwritten as a result of internal
* operations in the Peer Manager. A Peer Manager event is sent each time data is updated,
* regardless of whether the operation originated internally or from action by the user.
*
* @param[in] peer_id Peer ID to set data for.
* @param[in] data_id Which type of data to set.
* @param[in] p_data New value to set.
* @param[in] len The length in bytes of @p p_data.
* @param[out] p_token A token that identifies this particular store operation. The token can be
* used to identify events that pertain to this operation. This parameter can
* be NULL.
*
* @retval NRF_SUCCESS If the data is scheduled to be written to persistent storage.
* @retval NRF_ERROR_NULL If @p p_data is NULL.
* @retval NRF_ERROR_NOT_FOUND If no peer was found for the peer ID.
* @retval NRF_ERROR_BUSY If the underlying flash handler is busy with other flash
* operations. Try again after receiving a Peer Manager event.
* @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized.
*/
ret_code_t pm_peer_data_store(pm_peer_id_t peer_id,
pm_peer_data_id_t data_id,
void const * p_data,
uint16_t len,
pm_store_token_t * p_token);
/**@brief Function for setting or updating a peer's bonding data (@ref PM_PEER_DATA_ID_BONDING).
* @details See @ref pm_peer_data_store for parameters and return values. */
ret_code_t pm_peer_data_bonding_store(pm_peer_id_t peer_id,
pm_peer_data_bonding_t const * p_data,
pm_store_token_t * p_token);
/**@brief Function for setting or updating a peer's remote DB values. (@ref PM_PEER_DATA_ID_GATT_REMOTE).
* @details See @ref pm_peer_data_store for parameters and return values. */
ret_code_t pm_peer_data_remote_db_store(pm_peer_id_t peer_id,
ble_gatt_db_srv_t const * p_data,
uint16_t len,
pm_store_token_t * p_token);
/**@brief Function for setting or updating a peer's application data. (@ref PM_PEER_DATA_ID_APPLICATION).
* @details See @ref pm_peer_data_store for parameters and return values. */
ret_code_t pm_peer_data_app_data_store(pm_peer_id_t peer_id,
uint8_t const * p_data,
uint16_t len,
pm_store_token_t * p_token);
/** @}*/
/**
* @{
*/
/**@brief Function for deleting a peer's stored pieces of data.
*
* @details This function deletes specific data that is stored for a peer. Note that bonding data
* cannot be cleared separately.
*
* To delete all data for a peer (including bonding data), use @ref pm_peer_delete.
*
* @note Clearing data in persistent storage happens asynchronously.
*
* @param[in] peer_id Peer ID to clear data for.
* @param[in] data_id Which data to clear.
*
* @retval NRF_SUCCESS If the clear procedure was initiated successfully.
* @retval NRF_ERROR_INVALID_PARAM If @p data_id was PM_PEER_DATA_ID_BONDING or invalid, or
* @p peer_id was invalid.
* @retval NRF_ERROR_NOT_FOUND If there was no data to clear for this peer ID/data ID combination.
* @retval NRF_ERROR_BUSY If the underlying flash handler is busy with other flash
* operations. Try again after receiving a Peer Manager event.
* @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized.
* @retval NRF_ERROR_INTERNAL If another error occurred.
*/
ret_code_t pm_peer_data_delete(pm_peer_id_t peer_id, pm_peer_data_id_t data_id);
/**@brief Function for manually adding a peer to the persistent storage.
*
* @details This function allocates a new peer ID and stores bonding data for the new peer. The
* bonding data is necessary to prevent ambiguity/inconsistency in peer data.
*
* @param[in] p_bonding_data The bonding data of the new peer (must contain a public/static
* address or a non-zero IRK).
* @param[out] p_new_peer_id Peer ID for the new peer, or an existing peer if a match was found.
* @param[out] p_token A token that identifies this particular store operation (storing the
* bonding data). The token can be used to identify events that pertain
* to this operation. This parameter can be NULL.
*
* @retval NRF_SUCCESS If the store operation for bonding data was initiated successfully.
* @retval NRF_ERROR_NULL If @p p_bonding_data or @p p_new_peer_id is NULL.
* @retval NRF_ERROR_NO_MEM If there is no more space in persistent storage, so that the new
* peer cannot be allocated.
* @retval NRF_ERROR_BUSY If the underlying flash handler is busy with other flash
* operations. Try again after receiving a Peer Manager event.
* @retval NRF_ERROR_INVALID_PARAM If the bonding data is invalid.
* @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized.
*/
ret_code_t pm_peer_new(pm_peer_id_t * p_new_peer_id,
pm_peer_data_bonding_t * p_bonding_data,
pm_store_token_t * p_token);
/**@brief Function for freeing persistent storage for a peer.
*
* @details This function deletes every piece of data that is associated with the specified peer and
* frees the peer ID to be used for another peer. The deletion happens asynchronously, and
* the peer ID is not freed until the data is deleted. When the operation finishes, a @ref
* PM_EVT_PEER_DELETE_SUCCEEDED or @ref PM_EVT_PEER_DELETE_FAILED event is sent.
*
* @warning Use this function only when not connected to or connectable for the peer that is being
* deleted. If the peer is or becomes connected or data is manually written in flash during
* this procedure (until the success or failure event happens), the behavior is undefined.
*
* @param[in] peer_id Peer ID to be freed and have all associated data deleted.
*
* @retval NRF_SUCCESS If the operation was initiated successfully.
* @retval NRF_ERROR_INVALID_PARAM If the peer ID was not valid.
* @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized.
*/
ret_code_t pm_peer_delete(pm_peer_id_t peer_id);
/**@brief Function for deleting all data stored for all peers.
*
* @details This function sends either a @ref PM_EVT_PEERS_DELETE_SUCCEEDED or a @ref
* PM_EVT_PEERS_DELETE_FAILED event. In addition, a @ref PM_EVT_PEER_DELETE_SUCCEEDED or
* @ref PM_EVT_PEER_DELETE_FAILED event is sent for each deleted peer.
*
* @note No event is sent when there is no peer data in flash.
*
* @warning Use this function only when not connected or connectable. If a peer is or becomes
* connected or a @ref PM_PEER_DATA_FUNCTIONS function is used during this procedure (until
* the success or failure event happens), the behavior is undefined.
*
* @retval NRF_SUCCESS If the deletion process was initiated successfully.
* @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized.
* @retval NRF_ERROR_INTERNAL If another error occurred.
*/
ret_code_t pm_peers_delete(void);
/** @}*/
/**
* @{
*/
/**@brief Function for finding the highest and lowest ranked peers.
*
* @details The rank is saved in persistent storage under the data ID @ref PM_PEER_DATA_ID_PEER_RANK.
*
* @details The interpretation of rank is up to the user, because the rank is only updated by
* calling @ref pm_peer_rank_highest or by manipulating the value using a @ref
* PM_PEER_DATA_FUNCTIONS function.
*
* @note Any argument that is NULL is ignored.
*
* @param[out] p_highest_ranked_peer The peer ID with the highest rank of all peers, for example,
* the most recently used peer.
* @param[out] p_highest_rank The highest rank.
* @param[out] p_lowest_ranked_peer The peer ID with the lowest rank of all peers, for example,
* the least recently used peer.
* @param[out] p_lowest_rank The lowest rank.
*
* @retval NRF_SUCCESS If the operation completed successfully.
* @retval NRF_ERROR_NOT_FOUND If no peers were found.
* @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized.
* @retval NRF_ERROR_INTERNAL If another error occurred.
*/
ret_code_t pm_peer_ranks_get(pm_peer_id_t * p_highest_ranked_peer,
uint32_t * p_highest_rank,
pm_peer_id_t * p_lowest_ranked_peer,
uint32_t * p_lowest_rank);
/**@brief Function for updating the rank of a peer to be highest among all stored peers.
*
* @details If this function returns @ref NRF_SUCCESS, either a @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED or a
* @ref PM_EVT_PEER_DATA_UPDATE_FAILED event is sent with a @ref
* PM_STORE_TOKEN_INVALID store token when the operation is complete. Until the operation
* is complete, this function returns @ref NRF_ERROR_BUSY.
*
* When the operation is complete, the peer is the highest ranked peer as reported by
* @ref pm_peer_ranks_get.
*
* @note The @ref PM_EVT_PEER_DATA_UPDATE_SUCCEEDED event can arrive before the function returns if the peer
* is already ranked highest. In this case, the @ref pm_peer_data_update_succeeded_evt_t::flash_changed flag
* in the event will be false.
*
* @param[in] peer_id The peer to rank highest.
*
* @retval NRF_SUCCESS If the peer's rank is, or will be updated to be highest.
* @retval NRF_ERROR_BUSY If the underlying flash handler is busy with other flash
* operations, or if a previous call to this function has not
* completed. Try again after receiving a Peer Manager event.
* @retval NRF_ERROR_INTERNAL If another error occurred.
* @retval NRF_ERROR_INVALID_STATE If the Peer Manager is not initialized.
*/
ret_code_t pm_peer_rank_highest(pm_peer_id_t peer_id);
/** @}*/
/** @} */
/** @} */
#endif // PEER_MANAGER_H__

View File

@ -1,174 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 PEER_MANAGER_INTERNAL_H__
#define PEER_MANAGER_INTERNAL_H__
#include <stdint.h>
#include "sdk_errors.h"
#include "nrf_ble.h"
#include "nrf_ble_gap.h"
#include "peer_manager_types.h"
/**
* @cond NO_DOXYGEN
* @file peer_manager_types.h
*
* @addtogroup peer_manager
* @brief File containing definitions used solely inside the Peer Manager's modules.
* @{
*/
ANON_UNIONS_ENABLE
/**@brief One piece of data associated with a peer, together with its type.
*
* @note This type is deprecated.
*/
typedef struct
{
uint16_t length_words; /**< @brief The length of the data in words. */
pm_peer_data_id_t data_id; /**< @brief ID that specifies the type of data (defines which member of the union is used). */
union
{
pm_peer_data_bonding_t * p_bonding_data; /**< @brief The exchanged bond information in addition to metadata of the bonding. */
uint32_t * p_peer_rank; /**< @brief A value locally assigned to this peer. Its interpretation is up to the user. The rank is not set automatically by the Peer Manager, but it is assigned by the user using either @ref pm_peer_rank_highest or a @ref PM_PEER_DATA_FUNCTIONS function. */
bool * p_service_changed_pending; /**< @brief Whether a service changed indication should be sent to the peer. */
pm_peer_data_local_gatt_db_t * p_local_gatt_db; /**< @brief Persistent information pertaining to a peer GATT client. */
ble_gatt_db_srv_t * p_remote_gatt_db; /**< @brief Persistent information pertaining to a peer GATT server. */
uint8_t * p_application_data; /**< @brief Arbitrary data to associate with the peer. This data can be freely used by the application. */
void * p_all_data; /**< @brief Generic access pointer to the data. It is used only to handle the data without regard to type. */
}; /**< @brief The data. */
} pm_peer_data_t;
/**@brief Immutable version of @ref pm_peer_data_t.
*
* @note This type is deprecated.
*/
typedef struct
{
uint16_t length_words; /**< @brief The length of the data in words. */
pm_peer_data_id_t data_id; /**< @brief ID that specifies the type of data (defines which member of the union is used). */
union
{
pm_peer_data_bonding_t const * p_bonding_data; /**< @brief Immutable @ref pm_peer_data_t::p_bonding_data. */
uint32_t const * p_peer_rank; /**< @brief Immutable @ref pm_peer_data_t::p_peer_rank. */
bool const * p_service_changed_pending; /**< @brief Immutable @ref pm_peer_data_t::p_service_changed_pending. */
pm_peer_data_local_gatt_db_t const * p_local_gatt_db; /**< @brief Immutable @ref pm_peer_data_t::p_local_gatt_db. */
ble_gatt_db_srv_t const * p_remote_gatt_db; /**< @brief Immutable @ref pm_peer_data_t::p_remote_gatt_db. */
uint8_t const * p_application_data; /**< @brief Immutable @ref pm_peer_data_t::p_application_data. */
void const * p_all_data; /**< @brief Immutable @ref pm_peer_data_t::p_all_data. */
}; /**< @brief The data. */
} pm_peer_data_const_t;
ANON_UNIONS_DISABLE
/**@brief Version of @ref pm_peer_data_t that reflects the structure of peer data in flash.
*
* @note This type is deprecated.
*/
typedef pm_peer_data_const_t pm_peer_data_flash_t;
/**@brief Macro for calculating the flash size of bonding data.
*
* @return The number of words that the data takes in flash.
*/
#define PM_BONDING_DATA_N_WORDS() BYTES_TO_WORDS(sizeof(pm_peer_data_bonding_t))
/**@brief Macro for calculating the flash size of service changed pending state.
*
* @return The number of words that the data takes in flash.
*/
#define PM_SC_STATE_N_WORDS() BYTES_TO_WORDS(sizeof(bool))
/**@brief Macro for calculating the flash size of local GATT database data.
*
* @param[in] local_db_len The length, in bytes, of the database as reported by the SoftDevice.
*
* @return The number of words that the data takes in flash.
*/
#define PM_LOCAL_DB_N_WORDS(local_db_len) \
BYTES_TO_WORDS((local_db_len) + PM_LOCAL_DB_LEN_OVERHEAD_BYTES)
/**@brief Macro for calculating the length of a local GATT database attribute array.
*
* @param[in] n_words The number of words that the data takes in flash.
*
* @return The length of the database attribute array.
*/
#define PM_LOCAL_DB_LEN(n_words) (((n_words) * BYTES_PER_WORD) - PM_LOCAL_DB_LEN_OVERHEAD_BYTES)
/**@brief Macro for calculating the flash size of remote GATT database data.
*
* @param[in] service_count The number of services in the service array.
*
* @return The number of words that the data takes in flash.
*/
#define PM_REMOTE_DB_N_WORDS(service_count) BYTES_TO_WORDS(sizeof(ble_gatt_db_srv_t) * (service_count))
/**@brief Macro for calculating the flash size of remote GATT database data.
*
* @param[in] n_words The length in number of words.
*
* @return The number of words that the data takes in flash.
*/
#define PM_REMOTE_DB_N_SERVICES(n_words) (((n_words) * BYTES_PER_WORD) / sizeof(ble_gatt_db_srv_t))
/**@brief Function for calculating the flash size of the usage index.
*
* @return The number of words that the data takes in flash.
*/
#define PM_USAGE_INDEX_N_WORDS() BYTES_TO_WORDS(sizeof(uint32_t))
/** @}
* @endcond
*/
#endif /* PEER_MANAGER_INTERNAL_H__ */

View File

@ -1,202 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 peer_manager_types.h
*
* @addtogroup peer_manager
* @{
*/
#ifndef PEER_MANAGER_TYPES_H__
#define PEER_MANAGER_TYPES_H__
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "nrf.h"
#include "nrf_ble_gap.h"
#include "nrf_ble_hci.h"
#include "app_util.h"
#include "app_util_platform.h"
#include "ble_gatt_db.h"
/**@brief Handle to uniquely identify a peer for which we have persistently stored data.
*/
typedef uint16_t pm_peer_id_t;
/**@brief Type that is used for write prepares (used to reserve space in flash).
*/
typedef uint32_t pm_prepare_token_t;
/**@brief Type that is used to hold a reference to a stored item in flash.
*/
typedef uint32_t pm_store_token_t;
/**@brief Errors from security procedures in Peer Manager.
*
* @details Possible values are defined in @ref PM_SEC_ERRORS and @ref BLE_GAP_SEC_STATUS.
*/
typedef uint16_t pm_sec_error_code_t;
//lint -emacro(516,PM_LOCAL_DB_LEN_OVERHEAD_BYTES)
#define PM_PEER_ID_INVALID 0xFFFF /**< @brief Invalid value for @ref pm_peer_id_t. */
#define PM_STORE_TOKEN_INVALID 0 /**< @brief Invalid value for store token. */
#define PM_PEER_ID_N_AVAILABLE_IDS 256 /**< @brief The number of available peer IDs. */
#define PM_LOCAL_DB_LEN_OVERHEAD_BYTES offsetof(pm_peer_data_local_gatt_db_t, data) /**< @brief The static-length part of the local GATT data struct. */
#define PM_CONN_SEC_ERROR_BASE 0x1000 /**< @brief The base for Peer Manager defined errors. See @ref PM_SEC_ERRORS and @ref pm_sec_error_code_t. */
/**@defgroup PM_SEC_ERRORS Peer Manager defined security errors
*
* @details The first 256 numbers in this range correspond to the status codes in
* @ref BLE_HCI_STATUS_CODES.
* @{ */
#define PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING (PM_CONN_SEC_ERROR_BASE + 0x06) /**< @brief Encryption failed because the peripheral has lost the LTK for this bond. See also @ref BLE_HCI_STATUS_CODE_PIN_OR_KEY_MISSING and Table 3.7 ("Pairing Failed Reason Codes") in the Bluetooth Core Specification 4.2, section 3.H.3.5.5 (@linkBLEcore). */
#define PM_CONN_SEC_ERROR_MIC_FAILURE (PM_CONN_SEC_ERROR_BASE + 0x3D) /**< @brief Encryption ended with disconnection because of mismatching keys or a stray packet during a procedure. See the SoftDevice GAP Message Sequence Charts on encryption (@linkBLEMSCgap), the Bluetooth Core Specification 4.2, sections 6.B.5.1.3.1 and 3.H.3.5.5 (@linkBLEcore), and @ref BLE_HCI_CONN_TERMINATED_DUE_TO_MIC_FAILURE. */
#define PM_CONN_SEC_ERROR_DISCONNECT (PM_CONN_SEC_ERROR_BASE + 0x100) /**< @brief Pairing or encryption did not finish before the link disconnected for an unrelated reason. */
#define PM_CONN_SEC_ERROR_SMP_TIMEOUT (PM_CONN_SEC_ERROR_BASE + 0x101) /**< @brief Pairing/bonding could not start because an SMP time-out has already happened on this link. This means that no more pairing or bonding can happen on this link. To be able to pair or bond, the link must be disconnected and then reconnected. See Bluetooth Core Specification 4.2 section 3.H.3.4 (@linkBLEcore). */
/** @} */
/**@defgroup PM_PEER_ID_VERSIONS All versions of Peer IDs.
* @brief The data ID for each iteration of the data formats in flash.
* @details Each time the format (in flash) of a piece of peer data changes, the data ID will also
* be updated. This list of defines is a record of each data ID that has ever existed, and
* code that caters to legacy formats can find the relevant IDs here.
* @{ */
#define PM_PEER_DATA_ID_FIRST_VX 0 /**< @brief The smallest data ID. */
#define PM_PEER_DATA_ID_BONDING_V1 0 /**< @brief The data ID of the first version of bonding data. */
#define PM_PEER_DATA_ID_BONDING_V2 7 /**< @brief The data ID of the second version of bonding data. */
#define PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING_V1 1 /**< @brief The data ID of the first version of the service changed pending flag. */
#define PM_PEER_DATA_ID_GATT_LOCAL_V1 2 /**< @brief The data ID of the first version of local GATT data. */
#define PM_PEER_DATA_ID_GATT_LOCAL_V2 8 /**< @brief The data ID of the second version of local GATT data. */
#define PM_PEER_DATA_ID_GATT_REMOTE_V1 3 /**< @brief The data ID of the first version of remote GATT data. */
#define PM_PEER_DATA_ID_APPLICATION_V1 4 /**< @brief The data ID of the first version of application data. */
#define PM_PEER_DATA_ID_GATT_REMOTE_V2 5 /**< @brief The data ID of the second version of remote GATT data. */
#define PM_PEER_DATA_ID_PEER_RANK_V1 6 /**< @brief The data ID of the first version of the rank. */
#define PM_PEER_DATA_ID_LAST_VX 9 /**< @brief The data ID after the last valid one. */
#define PM_PEER_DATA_ID_INVALID_VX 0xFF /**< @brief A data ID guaranteed to be invalid. */
/**@}*/
/**@brief The different types of data associated with a peer.
*/
typedef enum
{
PM_PEER_DATA_ID_FIRST = PM_PEER_DATA_ID_FIRST_VX, /**< @brief The smallest data ID. */
PM_PEER_DATA_ID_BONDING = PM_PEER_DATA_ID_BONDING_V2, /**< @brief The data ID for bonding data. See @ref pm_peer_data_bonding_t. */
PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING = PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING_V1, /**< @brief The data ID for service changed state. */
PM_PEER_DATA_ID_GATT_LOCAL = PM_PEER_DATA_ID_GATT_LOCAL_V2, /**< @brief The data ID for local GATT data (sys attributes). See @ref pm_peer_data_local_gatt_db_t. */
PM_PEER_DATA_ID_GATT_REMOTE = PM_PEER_DATA_ID_GATT_REMOTE_V2, /**< @brief The data ID for remote GATT data. */
PM_PEER_DATA_ID_PEER_RANK = PM_PEER_DATA_ID_PEER_RANK_V1, /**< @brief The data ID for peer rank. See @ref pm_peer_rank_highest. */
PM_PEER_DATA_ID_APPLICATION = PM_PEER_DATA_ID_APPLICATION_V1, /**< @brief The data ID for application data. */
PM_PEER_DATA_ID_LAST = PM_PEER_DATA_ID_LAST_VX, /**< @brief One more than the highest data ID. */
PM_PEER_DATA_ID_INVALID = PM_PEER_DATA_ID_INVALID_VX, /**< @brief A data ID guaranteed to be invalid. */
} pm_peer_data_id_t;
/**@brief Different procedures that can lead to an encrypted link.
*/
typedef enum
{
PM_LINK_SECURED_PROCEDURE_ENCRYPTION, /**< @brief Using an LTK that was shared during a previous bonding procedure to encrypt the link. */
PM_LINK_SECURED_PROCEDURE_BONDING, /**< @brief A pairing procedure, followed by a bonding procedure. */
PM_LINK_SECURED_PROCEDURE_PAIRING, /**< @brief A pairing procedure with no bonding. */
} pm_conn_sec_procedure_t;
/**@brief Configuration of a security procedure.
*/
typedef struct
{
bool allow_repairing; /** @brief Whether to allow the peer to pair if it wants to, but is already bonded. If this is false, the procedure is rejected, and no more events are sent. Default: false. */
} pm_conn_sec_config_t;
/**@brief Data associated with a bond to a peer.
*/
typedef struct
{
uint8_t own_role; /**< @brief The role of the local device during bonding. */
ble_gap_id_key_t peer_id; /**< @brief The peer's peer address and identity resolution key. */
ble_gap_enc_key_t peer_ltk; /**< @brief The peer's long-term encryption key. */
ble_gap_enc_key_t own_ltk; /**< @brief Locally generated long-term encryption key, distributed to the peer. */
} pm_peer_data_bonding_t;
/**@brief Data on a local GATT database.
*/
typedef struct
{
uint32_t flags; /**< @brief Flags that describe the database attributes. */
uint16_t len; /**< @brief Size of the attribute array. */
#ifdef __ICCARM__ //IAR dosen't support "flexible array member" in c++ compilation
uint8_t data[1]; /**< @brief Array to hold the database attributes. */
#else
uint8_t data[]; /**< @brief Array to hold the database attributes. */
#endif
} pm_peer_data_local_gatt_db_t;
/**@brief Macro to check whether a data type is valid, thus one of the valid enum values.
*
* @param[in] data_id The data type to check.
*/
#define PM_PEER_DATA_ID_IS_VALID(data_id) \
( ((data_id) == PM_PEER_DATA_ID_BONDING) \
|| ((data_id) == PM_PEER_DATA_ID_SERVICE_CHANGED_PENDING)\
|| ((data_id) == PM_PEER_DATA_ID_GATT_LOCAL) \
|| ((data_id) == PM_PEER_DATA_ID_GATT_REMOTE) \
|| ((data_id) == PM_PEER_DATA_ID_PEER_RANK) \
|| ((data_id) == PM_PEER_DATA_ID_APPLICATION))
/** @} */
#endif /* PEER_MANAGER_TYPES_H__ */

View File

@ -1,149 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "pm_buffer.h"
#include <stdbool.h>
#include <string.h>
#include "nrf_error.h"
#include "pm_mutex.h"
#define BUFFER_IS_VALID(p_buffer) ((p_buffer != NULL) \
&& (p_buffer->p_memory != NULL) \
&& (p_buffer->p_mutex != NULL))
ret_code_t pm_buffer_init(pm_buffer_t * p_buffer,
uint8_t * p_buffer_memory,
uint32_t buffer_memory_size,
uint8_t * p_mutex_memory,
uint32_t mutex_memory_size,
uint32_t n_blocks,
uint32_t block_size)
{
if ( (p_buffer != NULL)
&& (p_buffer_memory != NULL)
&& (p_mutex_memory != NULL)
&& (buffer_memory_size >= (n_blocks*block_size))
&& (mutex_memory_size >= MUTEX_STORAGE_SIZE(n_blocks))
&& (n_blocks != 0)
&& (block_size != 0))
{
p_buffer->p_memory = p_buffer_memory;
p_buffer->p_mutex = p_mutex_memory;
p_buffer->n_blocks = n_blocks;
p_buffer->block_size = block_size;
pm_mutex_init(p_buffer->p_mutex, n_blocks);
return NRF_SUCCESS;
}
else
{
return NRF_ERROR_INVALID_PARAM;
}
}
uint8_t pm_buffer_block_acquire(pm_buffer_t * p_buffer, uint32_t n_blocks)
{
if (!BUFFER_IS_VALID(p_buffer))
{
return ( BUFFER_INVALID_ID );
}
uint8_t first_locked_mutex = BUFFER_INVALID_ID;
for (uint8_t i = 0; i < p_buffer->n_blocks; i++)
{
if (pm_mutex_lock(p_buffer->p_mutex, i))
{
if (first_locked_mutex == BUFFER_INVALID_ID)
{
first_locked_mutex = i;
}
if ((i - first_locked_mutex + 1) >= 0 && ((uint32_t) (i - first_locked_mutex + 1)) == n_blocks)
{
return first_locked_mutex;
}
}
else if (first_locked_mutex != BUFFER_INVALID_ID)
{
for (uint8_t j = first_locked_mutex; j < i; j++)
{
pm_buffer_release(p_buffer, j);
}
first_locked_mutex = BUFFER_INVALID_ID;
}
}
return ( BUFFER_INVALID_ID );
}
uint8_t * pm_buffer_ptr_get(pm_buffer_t * p_buffer, uint8_t id)
{
if (!BUFFER_IS_VALID(p_buffer))
{
return ( NULL );
}
if ( (id != BUFFER_INVALID_ID)
&& pm_mutex_lock_status_get(p_buffer->p_mutex, id) )
{
return ( &p_buffer->p_memory[id*p_buffer->block_size] );
}
else
{
return ( NULL );
}
}
void pm_buffer_release(pm_buffer_t * p_buffer, uint8_t id)
{
if ( BUFFER_IS_VALID(p_buffer)
&& (id != BUFFER_INVALID_ID)
&& pm_mutex_lock_status_get(p_buffer->p_mutex, id))
{
pm_mutex_unlock(p_buffer->p_mutex, id);
}
}

View File

@ -1,145 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 BUFFER_H__
#define BUFFER_H__
#include <stdint.h>
#include "sdk_errors.h"
#include "pm_mutex.h"
/**
* @cond NO_DOXYGEN
* @defgroup pm_buffer Buffer
* @ingroup peer_manager
* @{
* @brief An internal module of @ref peer_manager. This module provides a simple buffer.
*/
#define BUFFER_INVALID_ID 0xFF
#define PM_BUFFER_INIT(p_buffer, n_blocks, block_size, err_code) \
do \
{ \
static union { \
uint8_t u8[(n_blocks) * (block_size)]; \
uint32_t u32[1]; /*force allign to uint32_t*/ \
} buffer_memory; \
static uint8_t mutex_memory[MUTEX_STORAGE_SIZE(n_blocks)]; \
err_code = pm_buffer_init((p_buffer), \
buffer_memory.u8, \
(n_blocks) * (block_size), \
mutex_memory, \
MUTEX_STORAGE_SIZE(n_blocks), \
(n_blocks), \
(block_size)); \
} while(0)
typedef struct
{
uint8_t * p_memory; /**< The storage for all buffer entries. The size of the buffer must be n_blocks*block_size. */
uint8_t * p_mutex; /**< A mutex group with one mutex for each buffer entry. */
uint32_t n_blocks; /**< The number of allocatable blocks in the buffer. */
uint32_t block_size; /**< The size of each block in the buffer. */
} pm_buffer_t;
/**@brief Function for initializing a buffer instance.
*
* @param[out] p_buffer The buffer instance to initialize.
* @param[in] p_buffer_memory The memory this buffer will use.
* @param[in] buffer_memory_size The size of p_buffer_memory. This must be at least
* n_blocks*block_size.
* @param[in] p_mutex_memory The memory for the mutexes. This must be at least
* @ref MUTEX_STORAGE_SIZE(n_blocks).
* @param[in] mutex_memory_size The size of p_mutex_memory.
* @param[in] n_blocks The number of blocks in the buffer.
* @param[in] block_size The size of each block.
*
* @retval NRF_SUCCESS Successfully initialized buffer instance.
* @retval NRF_ERROR_INVALID_PARAM A parameter was 0 or NULL or a size was too small.
*/
ret_code_t pm_buffer_init(pm_buffer_t * p_buffer,
uint8_t * p_buffer_memory,
uint32_t buffer_memory_size,
uint8_t * p_mutex_memory,
uint32_t mutex_memory_size,
uint32_t n_blocks,
uint32_t block_size);
/**@brief Function for acquiring a buffer block in a buffer.
*
* @param[in] p_buffer The buffer instance acquire from.
* @param[in] n_blocks The number of contiguous blocks to acquire.
*
* @return The id of the acquired block, if successful.
* @retval BUFFER_INVALID_ID If unsuccessful.
*/
uint8_t pm_buffer_block_acquire(pm_buffer_t * p_buffer, uint32_t n_blocks);
/**@brief Function for getting a pointer to a specific buffer block.
*
* @param[in] p_buffer The buffer instance get from.
* @param[in] id The id of the buffer to get the pointer for.
*
* @return A pointer to the buffer for the specified id, if the id is valid.
* @retval NULL If the id is invalid.
*/
uint8_t * pm_buffer_ptr_get(pm_buffer_t * p_buffer, uint8_t id);
/**@brief Function for releasing a buffer block.
*
* @param[in] p_buffer The buffer instance containing the block to release.
* @param[in] id The id of the block to release.
*/
void pm_buffer_release(pm_buffer_t * p_buffer, uint8_t id);
#endif // BUFFER_H__
/**
* @}
* @endcond
*/

View File

@ -1,142 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "pm_mutex.h"
#include <stdbool.h>
#include <string.h>
#include "nrf_error.h"
#include "app_util_platform.h"
/**@brief Locks the mutex defined by the mask.
*
* @param p_mutex pointer to the mutex storage.
* @param mutex_mask the mask identifying the mutex position.
*
* @retval true if the mutex could be locked.
* @retval false if the mutex was already locked.
*/
static bool lock_by_mask(uint8_t * p_mutex, uint8_t mutex_mask)
{
bool success = false;
if ( (*p_mutex & mutex_mask) == 0 )
{
CRITICAL_REGION_ENTER();
if ( (*p_mutex & mutex_mask) == 0 )
{
*p_mutex |= mutex_mask;
success = true;
}
CRITICAL_REGION_EXIT();
}
return ( success );
}
void pm_mutex_init(uint8_t * p_mutex, uint16_t mutex_size)
{
if (p_mutex != NULL)
{
memset(&p_mutex[0], 0, MUTEX_STORAGE_SIZE(mutex_size));
}
}
bool pm_mutex_lock(uint8_t * p_mutex, uint16_t mutex_id)
{
if (p_mutex != NULL)
{
return ( lock_by_mask(&(p_mutex[mutex_id >> 3]), (1 << (mutex_id & 0x07))) );
}
else
{
return false;
}
}
void pm_mutex_unlock(uint8_t * p_mutex, uint16_t mutex_id)
{
uint8_t mutex_base = mutex_id >> 3;
uint8_t mutex_mask = (1 << (mutex_id & 0x07));
if ((p_mutex != NULL)
&& (p_mutex[mutex_base] & mutex_mask))
{
CRITICAL_REGION_ENTER();
p_mutex[mutex_base] &= ~mutex_mask;
CRITICAL_REGION_EXIT();
}
}
uint16_t pm_mutex_lock_first_available(uint8_t * p_mutex, uint16_t mutex_size)
{
if (p_mutex != NULL)
{
for ( uint16_t i = 0; i < mutex_size; i++ )
{
if ( lock_by_mask(&(p_mutex[i >> 3]), 1 << (i & 0x07)) )
{
return ( i );
}
}
}
return ( mutex_size );
}
bool pm_mutex_lock_status_get(uint8_t * p_mutex, uint16_t mutex_id)
{
if (p_mutex != NULL)
{
return ( (p_mutex[mutex_id >> 3] & (1 << (mutex_id & 0x07))) );
}
else
{
return true;
}
}

View File

@ -1,117 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 MUTEX_H__
#define MUTEX_H__
#include <stdint.h>
#include <stdbool.h>
/**
* @cond NO_DOXYGEN
* @defgroup pm_mutex Mutex
* @ingroup peer_manager
* @{
* @brief An internal module of @ref peer_manager. This module provides thread-safe mutexes.
*/
/**@brief Defines the storage size of a specified mutex group.
*
* @param number_of_mutexes the number of mutexes in the group.
*/
#define MUTEX_STORAGE_SIZE(number_of_mutexes) ((7 + (number_of_mutexes)) >> 3)
/**@brief Initializes a mutex group.
*
* @param[in] p_mutex Pointer to the mutex group. See @ref MUTEX_STORAGE_SIZE().
* @param[in] mutex_size The size of the mutex group in number of mutexes.
*/
void pm_mutex_init(uint8_t * p_mutex, uint16_t mutex_size);
/**@brief Locks the mutex specified by the bit id.
*
* @param[inout] p_mutex Pointer to the mutex group.
* @param[in] mutex_bit_id The bit id of the mutex.
*
* @retval true if it was possible to lock the mutex.
* @retval false otherwise.
*/
bool pm_mutex_lock(uint8_t * p_mutex, uint16_t mutex_bit_id);
/**@brief Locks the first unlocked mutex within the mutex group.
*
* @param[in, out] p_mutex Pointer to the mutex group.
* @param[in] mutex_size The size of the mutex group.
*
* @return The first unlocked mutex id in the group.
* @retval group-size if there was no unlocked mutex available.
*/
uint16_t pm_mutex_lock_first_available(uint8_t * p_mutex, uint16_t mutex_size);
/**@brief Unlocks the mutex specified by the bit id.
*
* @param[in, out] p_mutex Pointer to the mutex group.
* @param[in] mutex_bit_id The bit id of the mutex.
*/
void pm_mutex_unlock(uint8_t * p_mutex, uint16_t mutex_bit_id);
/**@brief Gets the locking status of the specified mutex.
*
* @param[in, out] p_mutex Pointer to the mutex group.
* @param[in] mutex_bit_id The bit id of the mutex.
*
* @retval true if the mutex was locked.
* @retval false otherwise.
*/
bool pm_mutex_lock_status_get(uint8_t * p_mutex, uint16_t mutex_bit_id);
#endif // MUTEX_H__
/** @}
* @endcond
*/

View File

@ -1,910 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "security_dispatcher.h"
#include <string.h>
#include "nrf_ble.h"
#include "nrf_ble_gap.h"
#include "ble_conn_state.h"
#include "peer_manager_types.h"
#include "peer_database.h"
#include "id_manager.h"
#include "sdk_common.h"
#define MAX_REGISTRANTS 3 /**< The number of user that can register with the module. */
typedef struct
{
smd_evt_handler_t evt_handlers[MAX_REGISTRANTS];
uint8_t n_registrants;
ble_conn_state_user_flag_id_t flag_id_sec_proc;
ble_conn_state_user_flag_id_t flag_id_sec_proc_pairing;
ble_conn_state_user_flag_id_t flag_id_sec_proc_new_peer;
ble_gap_lesc_p256_pk_t peer_pk;
} smd_t;
static smd_t m_smd =
{
.flag_id_sec_proc = BLE_CONN_STATE_USER_FLAG_INVALID,
.flag_id_sec_proc_pairing = BLE_CONN_STATE_USER_FLAG_INVALID,
.flag_id_sec_proc_new_peer = BLE_CONN_STATE_USER_FLAG_INVALID,
};
#define MODULE_INITIALIZED (m_smd.n_registrants > 0) /**< Expression which is true when the module is initialized. */
#include "sdk_macros.h"
static void evt_send(smd_evt_t * p_event)
{
for (int i = 0; i < m_smd.n_registrants; i++)
{
m_smd.evt_handlers[i](p_event);
}
}
static void sec_start_send(uint16_t conn_handle, pm_conn_sec_procedure_t procedure)
{
smd_evt_t evt =
{
.evt_id = SMD_EVT_SEC_PROCEDURE_START,
.conn_handle = conn_handle,
.params = {.sec_procedure_start = {.procedure = procedure}}
};
evt_send(&evt);
}
/**@brief Event handler for events from the peer_database module.
*
* @param[in] p_event The event that has happened.
*/
static void pdb_evt_handler(pdb_evt_t const * p_event)
{
if ((p_event->evt_id == PDB_EVT_WRITE_BUF_STORED) && (p_event->data_id == PM_PEER_DATA_ID_BONDING))
{
smd_evt_t evt =
{
.evt_id = SMD_EVT_BONDING_INFO_STORED,
.conn_handle = im_conn_handle_get(p_event->peer_id),
.params = {.bonding_info_stored =
{
.peer_id = p_event->peer_id,
}}
};
evt_send(&evt);
}
}
/**@brief Function for processing the @ref BLE_GAP_EVT_SEC_PARAMS_REQUEST event from the SoftDevice.
*
* @param[in] p_gap_evt The event from the SoftDevice.
*/
static void sec_params_request_process(ble_gap_evt_t * p_gap_evt)
{
smd_evt_t evt =
{
.evt_id = SMD_EVT_PARAMS_REQ,
.conn_handle = p_gap_evt->conn_handle
};
evt_send(&evt);
return;
}
/**@brief Function for administrative actions to be taken when a security process has been attempted.
*
* @param[in] conn_handle The connection the security process was attempted on.
* @param[in] peer_id The peer ID given to the connected peer.
* @param[in] success Whether the process was started successfully.
* @param[in] pairing Whether the process was a pairing process.
* @param[in] new_peer_created Whether a new peer was created during the process attempt.
*/
static void sec_proc_start(uint16_t conn_handle,
pm_peer_id_t peer_id,
bool success,
bool pairing,
bool new_peer_created)
{
ble_conn_state_user_flag_set(conn_handle, m_smd.flag_id_sec_proc, success);
if (success)
{
ble_conn_state_user_flag_set(conn_handle, m_smd.flag_id_sec_proc_pairing, pairing);
ble_conn_state_user_flag_set(conn_handle, m_smd.flag_id_sec_proc_new_peer, new_peer_created);
if(new_peer_created)
{
im_new_peer_id(conn_handle, peer_id);
}
}
else
{
if(new_peer_created)
{
ret_code_t err_code = im_peer_free(peer_id); // Attempt to free allocated peer.
UNUSED_VARIABLE(err_code);
}
}
}
/**@brief Function for processing the @ref BLE_GAP_EVT_SEC_INFO_REQUEST event from the SoftDevice.
*
* @param[in] p_gap_evt The event from the SoftDevice.
*/
static void sec_info_request_process(ble_gap_evt_t * p_gap_evt)
{
ret_code_t err_code;
ble_gap_enc_info_t const * p_enc_info = NULL;
pm_peer_data_flash_t peer_data;
pm_peer_id_t peer_id = im_peer_id_get_by_master_id(&p_gap_evt->params.sec_info_request.master_id);
smd_evt_t evt;
evt.conn_handle = p_gap_evt->conn_handle;
if (peer_id == PM_PEER_ID_INVALID)
{
peer_id = im_peer_id_get_by_conn_handle(p_gap_evt->conn_handle);
}
if (peer_id != PM_PEER_ID_INVALID)
{
err_code = pdb_read_buf_get(peer_id, PM_PEER_DATA_ID_BONDING, &peer_data, NULL);
if (err_code == NRF_SUCCESS)
{
// There is stored bonding data for this peer.
ble_gap_enc_key_t const * p_existing_key = &peer_data.p_bonding_data->own_ltk;
if ( p_existing_key->enc_info.lesc
|| (im_master_ids_compare(&p_existing_key->master_id,
&p_gap_evt->params.sec_info_request.master_id)))
{
p_enc_info = &p_existing_key->enc_info;
}
}
}
// All return values from the following can be safely ignored.
err_code = sd_ble_gap_sec_info_reply(p_gap_evt->conn_handle, p_enc_info, NULL, NULL);
if (err_code != NRF_SUCCESS)
{
evt.evt_id = SMD_EVT_ERROR_UNEXPECTED;
evt.params.error_unexpected.error = err_code;
evt_send(&evt);
}
else if (p_enc_info == NULL)
{
evt.evt_id = SMD_EVT_LINK_ENCRYPTION_FAILED;
evt.params.link_encryption_failed.error = PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING;
evt.params.link_encryption_failed.error_src = BLE_GAP_SEC_STATUS_SOURCE_LOCAL;
evt_send(&evt);
sec_proc_start(p_gap_evt->conn_handle, peer_id, false, false, false);
}
else
{
sec_start_send(p_gap_evt->conn_handle, PM_LINK_SECURED_PROCEDURE_ENCRYPTION);
sec_proc_start(p_gap_evt->conn_handle, peer_id, err_code == NRF_SUCCESS, false, false);
}
return;
}
/**@brief Function for processing the @ref BLE_GAP_EVT_SEC_REQUEST event from the SoftDevice.
*
* @param[in] p_gap_evt The event from the SoftDevice.
*/
static void sec_request_process(ble_gap_evt_t * p_gap_evt)
{
smd_evt_t evt =
{
.evt_id = SMD_EVT_SLAVE_SECURITY_REQ,
.conn_handle = p_gap_evt->conn_handle,
.params =
{
.slave_security_req =
{
.bond = p_gap_evt->params.sec_request.bond,
.mitm = p_gap_evt->params.sec_request.mitm,
}
}
};
evt_send(&evt);
return;
}
/**@brief Function for processing the @ref BLE_GAP_EVT_AUTH_STATUS event from the SoftDevice, when
* the auth_status is success.
*
* @param[in] p_gap_evt The event from the SoftDevice.
*/
static void auth_status_success_process(ble_gap_evt_t * p_gap_evt)
{
ret_code_t err_code = NRF_SUCCESS;
uint8_t role = ble_conn_state_role(p_gap_evt->conn_handle);
pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(p_gap_evt->conn_handle);
ble_gap_sec_kdist_t kdist_own = p_gap_evt->params.auth_status.kdist_own;
ble_gap_sec_kdist_t kdist_peer = p_gap_evt->params.auth_status.kdist_peer;
ble_conn_state_user_flag_set(p_gap_evt->conn_handle, m_smd.flag_id_sec_proc, false);
if (role == BLE_GAP_ROLE_INVALID)
{
/* Unlikely, but maybe possible? */
return;
}
if (p_gap_evt->params.auth_status.bonded)
{
err_code = pdb_write_buf_store(peer_id, PM_PEER_DATA_ID_BONDING);
if (err_code != NRF_SUCCESS)
{
/* Unexpected */
smd_evt_t error_evt;
error_evt.evt_id = SMD_EVT_ERROR_BONDING_INFO;
error_evt.conn_handle = p_gap_evt->conn_handle;
error_evt.params.error_bonding_info.peer_id = peer_id;
error_evt.params.error_bonding_info.error = err_code;
evt_send(&error_evt);
}
}
else if (ble_conn_state_user_flag_get(p_gap_evt->conn_handle, m_smd.flag_id_sec_proc_new_peer))
{
ret_code_t err_code_free = im_peer_free(peer_id);
UNUSED_VARIABLE(err_code_free); // Errors can be safely ignored.
}
smd_evt_t pairing_success_evt;
pairing_success_evt.evt_id = SMD_EVT_PAIRING_SUCCESS;
pairing_success_evt.conn_handle = p_gap_evt->conn_handle;
pairing_success_evt.params.pairing_success.bonded = p_gap_evt->params.auth_status.bonded;
pairing_success_evt.params.pairing_success.mitm = p_gap_evt->params.auth_status.sm1_levels.lv3;
pairing_success_evt.params.pairing_success.kdist_own = kdist_own;
pairing_success_evt.params.pairing_success.kdist_peer = kdist_peer;
evt_send(&pairing_success_evt);
return;
}
/**@brief Function for cleaning up after a failed pairing procedure.
*
* @param[in] conn_handle The handle of the connection the pairing procedure happens on.
* @param[in] peer_id The peer id used in the pairing procedure.
* @param[in] error The error the procedure failed with.
* @param[in] error_src The party that raised the error. See @ref BLE_GAP_SEC_STATUS_SOURCES.
*/
static void pairing_failure(uint16_t conn_handle,
pm_peer_id_t peer_id,
pm_sec_error_code_t error,
uint8_t error_src)
{
ret_code_t err_code = NRF_SUCCESS;
smd_evt_t evt =
{
.evt_id = SMD_EVT_PAIRING_FAIL,
.conn_handle = conn_handle,
.params =
{
.pairing_failed =
{
.error = error,
.error_src = error_src,
}
}
};
if(ble_conn_state_user_flag_get(conn_handle, m_smd.flag_id_sec_proc_new_peer))
{
// The peer_id was created during the procedure, and should be freed, because no data is
// stored under it.
err_code = im_peer_free(peer_id); // Attempt to free allocated peer.
UNUSED_VARIABLE(err_code);
}
else
{
err_code = pdb_write_buf_release(peer_id, PM_PEER_DATA_ID_BONDING);
if ((err_code != NRF_SUCCESS) && (err_code == NRF_ERROR_NOT_FOUND /* No buffer was allocated */))
{
smd_evt_t error_evt;
error_evt.evt_id = SMD_EVT_ERROR_UNEXPECTED;
error_evt.conn_handle = conn_handle;
error_evt.params.error_unexpected.error = err_code;
evt_send(&error_evt);
}
}
ble_conn_state_user_flag_set(conn_handle, m_smd.flag_id_sec_proc, false);
evt_send(&evt);
return;
}
/**@brief Function for cleaning up after a failed encryption procedure.
*
* @param[in] conn_handle The handle of the connection the encryption procedure happens on.
* @param[in] error The error the procedure failed with.
* @param[in] error_src The party that raised the error. See @ref BLE_GAP_SEC_STATUS_SOURCES.
*/
static void encryption_failure(uint16_t conn_handle,
pm_sec_error_code_t error,
uint8_t error_src)
{
smd_evt_t evt =
{
.evt_id = SMD_EVT_LINK_ENCRYPTION_FAILED,
.conn_handle = conn_handle,
.params =
{
.link_encryption_failed =
{
.error = error,
.error_src = error_src,
}
}
};
ble_conn_state_user_flag_set(conn_handle, m_smd.flag_id_sec_proc, false);
evt_send(&evt);
return;
}
/**@brief Function for possibly cleaning up after a failed pairing or encryption procedure.
*
* @param[in] conn_handle The handle of the connection the pairing procedure happens on.
* @param[in] peer_id The peer id used in the pairing procedure.
* @param[in] error The error the procedure failed with.
* @param[in] error_src The party that raised the error. See @ref BLE_GAP_SEC_STATUS_SOURCES.
*/
static void link_secure_failure(uint16_t conn_handle,
pm_sec_error_code_t error,
uint8_t error_src)
{
if (ble_conn_state_user_flag_get(conn_handle, m_smd.flag_id_sec_proc))
{
pm_peer_id_t peer_id = im_peer_id_get_by_conn_handle(conn_handle);
if (peer_id != PM_PEER_ID_INVALID)
{
if (ble_conn_state_user_flag_get(conn_handle, m_smd.flag_id_sec_proc_pairing))
{
pairing_failure(conn_handle, peer_id, error, error_src);
}
else
{
encryption_failure(conn_handle, error, error_src);
}
}
}
}
/**@brief Function for processing the @ref BLE_GAP_EVT_DISCONNECT event from the SoftDevice.
*
* @param[in] p_gap_evt The event from the SoftDevice.
*/
static void disconnect_process(ble_gap_evt_t * p_gap_evt)
{
pm_sec_error_code_t error = (p_gap_evt->params.disconnected.reason
== BLE_HCI_CONN_TERMINATED_DUE_TO_MIC_FAILURE)
? PM_CONN_SEC_ERROR_MIC_FAILURE : PM_CONN_SEC_ERROR_DISCONNECT;
link_secure_failure(p_gap_evt->conn_handle, error, BLE_GAP_SEC_STATUS_SOURCE_LOCAL);
}
/**@brief Function for processing the @ref BLE_GAP_EVT_AUTH_STATUS event from the SoftDevice, when
* the auth_status is failure.
*
* @param[in] p_gap_evt The event from the SoftDevice.
*/
static void auth_status_failure_process(ble_gap_evt_t * p_gap_evt)
{
link_secure_failure(p_gap_evt->conn_handle,
p_gap_evt->params.auth_status.auth_status,
p_gap_evt->params.auth_status.error_src);
}
/**@brief Function for processing the @ref BLE_GAP_EVT_AUTH_STATUS event from the SoftDevice.
*
* @param[in] p_gap_evt The event from the SoftDevice.
*/
static void auth_status_process(ble_gap_evt_t * p_gap_evt)
{
switch (p_gap_evt->params.auth_status.auth_status)
{
case BLE_GAP_SEC_STATUS_SUCCESS:
auth_status_success_process(p_gap_evt);
break;
default:
auth_status_failure_process(p_gap_evt);
break;
}
}
/**@brief Function for processing the @ref BLE_GAP_EVT_CONN_SEC_UPDATE event from the SoftDevice.
*
* @param[in] p_gap_evt The event from the SoftDevice.
*/
static void conn_sec_update_process(ble_gap_evt_t * p_gap_evt)
{
if (ble_conn_state_encrypted(p_gap_evt->conn_handle))
{
if (!ble_conn_state_user_flag_get(p_gap_evt->conn_handle, m_smd.flag_id_sec_proc_pairing))
{
ble_conn_state_user_flag_set(p_gap_evt->conn_handle, m_smd.flag_id_sec_proc, false);
}
smd_evt_t evt;
evt.conn_handle = p_gap_evt->conn_handle;
evt.evt_id = SMD_EVT_LINK_ENCRYPTION_UPDATE;
evt.params.link_encryption_update.mitm_protected
= ble_conn_state_mitm_protected(p_gap_evt->conn_handle);
evt_send(&evt);
}
else
{
encryption_failure(p_gap_evt->conn_handle,
PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING,
BLE_GAP_SEC_STATUS_SOURCE_REMOTE);
}
}
/**@brief Funtion for initializing a BLE Connection State user flag.
*
* @param[out] flag_id The flag to initialize.
*/
static void flag_id_init(ble_conn_state_user_flag_id_t * p_flag_id)
{
if (*p_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID)
{
*p_flag_id = ble_conn_state_user_flag_acquire();
}
}
ret_code_t smd_register(smd_evt_handler_t evt_handler)
{
ret_code_t err_code = NRF_SUCCESS;
if (evt_handler == NULL)
{
err_code = NRF_ERROR_NULL;
}
else
{
if (!MODULE_INITIALIZED)
{
flag_id_init(&m_smd.flag_id_sec_proc);
flag_id_init(&m_smd.flag_id_sec_proc_pairing);
flag_id_init(&m_smd.flag_id_sec_proc_new_peer);
if (m_smd.flag_id_sec_proc_new_peer == BLE_CONN_STATE_USER_FLAG_INVALID)
{
err_code = NRF_ERROR_INTERNAL;
}
else
{
err_code = pdb_register(pdb_evt_handler);
}
}
if ((err_code == NRF_SUCCESS))
{
if ((m_smd.n_registrants < MAX_REGISTRANTS))
{
m_smd.evt_handlers[m_smd.n_registrants++] = evt_handler;
}
else
{
err_code = NRF_ERROR_NO_MEM;
}
}
}
return err_code;
}
ret_code_t smd_params_reply(uint16_t conn_handle,
ble_gap_sec_params_t * p_sec_params,
ble_gap_lesc_p256_pk_t * p_public_key)
{
VERIFY_MODULE_INITIALIZED();
uint8_t role = ble_conn_state_role(conn_handle);
pm_peer_id_t peer_id = PM_PEER_ID_INVALID;
ret_code_t err_code = NRF_SUCCESS;
uint8_t sec_status = BLE_GAP_SEC_STATUS_SUCCESS;
ble_gap_sec_keyset_t sec_keyset;
bool new_peer_created = false;
memset(&sec_keyset, 0, sizeof(ble_gap_sec_keyset_t));
if (role == BLE_GAP_ROLE_INVALID)
{
return BLE_ERROR_INVALID_CONN_HANDLE;
}
if (p_sec_params == NULL)
{
// NULL params means reject pairing.
sec_status = BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP;
}
else if (p_sec_params->bond)
{
// Bonding is to be performed, prepare to receive bonding data.
pm_peer_data_t peer_data;
peer_id = im_peer_id_get_by_conn_handle(conn_handle);
if (peer_id == PM_PEER_ID_INVALID)
{
// Peer is unknown to us, allocate a new peer ID for it.
peer_id = pdb_peer_allocate();
if (peer_id != PM_PEER_ID_INVALID)
{
new_peer_created = true;
}
else
{
err_code = NRF_ERROR_INTERNAL;
}
}
if (err_code == NRF_SUCCESS)
{
// Peer ID is ready, acquire a memory buffer to receive bonding data into.
err_code = pdb_write_buf_get(peer_id, PM_PEER_DATA_ID_BONDING, 1, &peer_data);
if (err_code == NRF_SUCCESS)
{
memset(peer_data.p_bonding_data, 0, sizeof(pm_peer_data_bonding_t));
peer_data.p_bonding_data->own_role = role;
sec_keyset.keys_own.p_enc_key = &peer_data.p_bonding_data->own_ltk;
sec_keyset.keys_own.p_pk = p_public_key;
sec_keyset.keys_peer.p_enc_key = &peer_data.p_bonding_data->peer_ltk;
sec_keyset.keys_peer.p_id_key = &peer_data.p_bonding_data->peer_id;
sec_keyset.keys_peer.p_pk = &m_smd.peer_pk;
ret_code_t err_code_addr = im_ble_addr_get(conn_handle, &peer_data.p_bonding_data->peer_id.id_addr_info); // Retrieve the address the peer used during connection establishment. This address will be overwritten if ID is shared. Should not fail.
UNUSED_VARIABLE(err_code_addr);
// Buffer is OK, reserve room in flash for the data.
err_code = pdb_write_buf_store_prepare(peer_id, PM_PEER_DATA_ID_BONDING);
}
}
}
else
{
// Pairing only, no action needed.
}
if (err_code == NRF_SUCCESS)
{
// Everything OK, reply to SoftDevice. If an error happened, the user is given an
// opportunity to change the parameters and retry the call.
if (role == BLE_GAP_ROLE_CENTRAL)
{
err_code = sd_ble_gap_sec_params_reply(conn_handle, sec_status, NULL, &sec_keyset);
}
else
{
err_code = sd_ble_gap_sec_params_reply(conn_handle, sec_status, p_sec_params, &sec_keyset);
if ((p_sec_params != NULL) && (err_code == NRF_SUCCESS))
{
pm_conn_sec_procedure_t procedure = p_sec_params->bond
? PM_LINK_SECURED_PROCEDURE_BONDING
: PM_LINK_SECURED_PROCEDURE_PAIRING;
sec_start_send(conn_handle, procedure);
}
}
}
sec_proc_start(conn_handle,
peer_id,
(err_code == NRF_SUCCESS) && (sec_status != BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP),
true,
new_peer_created);
return err_code;
}
static ret_code_t link_secure_central_existing_peer(uint16_t conn_handle,
ble_gap_sec_params_t * p_sec_params,
bool force_repairing,
pm_peer_id_t peer_id,
pm_conn_sec_procedure_t * procedure)
{
pm_peer_data_flash_t peer_data;
pm_peer_data_t dummy_peer_data;
ret_code_t err_code;
ble_gap_enc_key_t const * p_existing_key = NULL;
bool lesc = false;
err_code = pdb_read_buf_get(peer_id, PM_PEER_DATA_ID_BONDING, &peer_data, NULL);
if (err_code == NRF_SUCCESS)
{
// Use peer's key since they are peripheral.
p_existing_key = &(peer_data.p_bonding_data->peer_ltk);
lesc = peer_data.p_bonding_data->own_ltk.enc_info.lesc;
if (lesc) // LESC was used during bonding.
{
// For LESC, always use own key.
p_existing_key = &(peer_data.p_bonding_data->own_ltk);
}
}
if (!force_repairing
&& (err_code == NRF_SUCCESS)
&& (p_existing_key != NULL)
&& (lesc || im_master_id_is_valid(&(p_existing_key->master_id)))) /* There is a valid LTK stored. */
//&& (p_existing_key->enc_info.auth >= p_sec_params->mitm) /* The requested MITM security is at or below the existing level. */
//&& (!p_sec_params->mitm || (lesc >= p_sec_params->lesc))) /* The requested LESC security is at or below the existing level. We only care about LESC if MITM is required. */
{
err_code = sd_ble_gap_encrypt(conn_handle, &(p_existing_key->master_id), &(p_existing_key->enc_info));
*procedure = PM_LINK_SECURED_PROCEDURE_ENCRYPTION;
}
else if ((err_code == NRF_SUCCESS) || (err_code == NRF_ERROR_NOT_FOUND))
{
/* Re-pairing is needed, because there is no LTK available or the existing key is not
secure enough */
err_code = NRF_SUCCESS;
if (p_sec_params->bond)
{
err_code = pdb_write_buf_get(peer_id, PM_PEER_DATA_ID_BONDING, 1, &dummy_peer_data);
if (err_code == NRF_SUCCESS)
{
err_code = pdb_write_buf_store_prepare(peer_id, PM_PEER_DATA_ID_BONDING);
}
}
if (err_code == NRF_SUCCESS)
{
err_code = sd_ble_gap_authenticate(conn_handle, p_sec_params);
}
if (err_code != NRF_SUCCESS)
{
ret_code_t err_code_release = pdb_write_buf_release(peer_id, PM_PEER_DATA_ID_BONDING);
if ((err_code_release != NRF_SUCCESS) && (err_code_release != NRF_ERROR_NOT_FOUND))
{
err_code = NRF_ERROR_INTERNAL;
}
}
}
sec_proc_start(conn_handle,
peer_id,
err_code == NRF_SUCCESS,
*procedure != PM_LINK_SECURED_PROCEDURE_ENCRYPTION,
false);
return err_code;
}
static ret_code_t link_secure_central_new_peer(uint16_t conn_handle,
ble_gap_sec_params_t * p_sec_params)
{
pm_peer_id_t peer_id = pdb_peer_allocate();
pm_peer_data_t dummy_peer_data;
ret_code_t err_code;
if (peer_id != PM_PEER_ID_INVALID)
{
err_code = pdb_write_buf_get(peer_id, PM_PEER_DATA_ID_BONDING, 1, &dummy_peer_data);
if (err_code == NRF_SUCCESS)
{
err_code = pdb_write_buf_store_prepare(peer_id, PM_PEER_DATA_ID_BONDING);
}
if (err_code == NRF_SUCCESS)
{
err_code = sd_ble_gap_authenticate(conn_handle, p_sec_params);
}
if (err_code != NRF_SUCCESS)
{
ret_code_t err_code_free = pdb_write_buf_release(peer_id, PM_PEER_DATA_ID_BONDING);
if ((err_code_free != NRF_SUCCESS) && (err_code_free != NRF_ERROR_NOT_FOUND))
{
err_code = NRF_ERROR_INTERNAL;
}
}
}
else
{
err_code = NRF_ERROR_INTERNAL;
}
sec_proc_start(conn_handle,
peer_id,
err_code == NRF_SUCCESS,
true,
peer_id != PM_PEER_ID_INVALID);
return err_code;
}
static ret_code_t link_secure_central(uint16_t conn_handle,
ble_gap_sec_params_t * p_sec_params,
bool force_repairing)
{
ret_code_t err_code;
pm_peer_id_t peer_id;
if (p_sec_params == NULL)
{
return sd_ble_gap_authenticate(conn_handle, NULL);
}
pm_conn_sec_procedure_t procedure = p_sec_params->bond ? PM_LINK_SECURED_PROCEDURE_BONDING
: PM_LINK_SECURED_PROCEDURE_PAIRING;
peer_id = im_peer_id_get_by_conn_handle(conn_handle);
if (peer_id != PM_PEER_ID_INVALID)
{
// There is already data in flash for this peer.
err_code = link_secure_central_existing_peer(conn_handle,
p_sec_params,
force_repairing,
peer_id,
&procedure);
}
else if (p_sec_params->bond)
{
// New peer is required.
err_code = link_secure_central_new_peer(conn_handle, p_sec_params);
}
else
{
// No bonding, only pairing.
err_code = sd_ble_gap_authenticate(conn_handle, p_sec_params);
sec_proc_start(conn_handle, peer_id, err_code == NRF_SUCCESS, true, false);
}
if (err_code == NRF_SUCCESS)
{
sec_start_send(conn_handle, procedure);
}
return err_code;
}
static ret_code_t link_secure_peripheral(uint16_t conn_handle, ble_gap_sec_params_t * p_sec_params)
{
VERIFY_PARAM_NOT_NULL(p_sec_params);
ret_code_t err_code = sd_ble_gap_authenticate(conn_handle, p_sec_params);
return err_code;
}
ret_code_t smd_link_secure(uint16_t conn_handle,
ble_gap_sec_params_t * p_sec_params,
bool force_repairing)
{
VERIFY_MODULE_INITIALIZED();
uint8_t role = ble_conn_state_role(conn_handle);
switch (role)
{
case BLE_GAP_ROLE_CENTRAL:
return link_secure_central(conn_handle, p_sec_params, force_repairing);
case BLE_GAP_ROLE_PERIPH:
return link_secure_peripheral(conn_handle, p_sec_params);
default:
return BLE_ERROR_INVALID_CONN_HANDLE;
}
}
void smd_ble_evt_handler(ble_evt_t * p_ble_evt)
{
switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_DISCONNECTED:
disconnect_process(&(p_ble_evt->evt.gap_evt));
break;
case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
sec_params_request_process(&(p_ble_evt->evt.gap_evt));
break;
case BLE_GAP_EVT_SEC_INFO_REQUEST:
sec_info_request_process(&(p_ble_evt->evt.gap_evt));
break;
case BLE_GAP_EVT_SEC_REQUEST:
sec_request_process(&(p_ble_evt->evt.gap_evt));
break;
case BLE_GAP_EVT_AUTH_STATUS:
auth_status_process(&(p_ble_evt->evt.gap_evt));
break;
case BLE_GAP_EVT_CONN_SEC_UPDATE:
conn_sec_update_process(&(p_ble_evt->evt.gap_evt));
break;
};
}

View File

@ -1,281 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 SECURITY_DISPATCHER_H__
#define SECURITY_DISPATCHER_H__
#include <stdint.h>
#include "sdk_errors.h"
#include "nrf_ble.h"
#include "nrf_ble_gap.h"
#include "peer_manager_types.h"
/**
* @cond NO_DOXYGEN
* @defgroup security_dispatcher Security Dispatcher
* @ingroup peer_manager
* @{
* @brief An internal module of @ref peer_manager. A module for streamlining pairing, bonding, and
* encryption, including flash storage of shared data.
*
*/
/**@brief Events that can come from the Security Dispatcher module.
*/
typedef enum
{
SMD_EVT_PARAMS_REQ, /**< Parameters are required for a pairing procedure on the specified connection. The user must provide them using @ref smd_params_reply. */
SMD_EVT_SLAVE_SECURITY_REQ, /**< The peer (slave) has requested link encryption. Call @ref smd_link_secure to honor the request. The data in the event structure must be used in the parameters. */
SMD_EVT_SEC_PROCEDURE_START, /**< A security procedure has started. */
SMD_EVT_PAIRING_SUCCESS, /**< A pairing procedure (and bonding if applicable) has completed with success. */
SMD_EVT_PAIRING_FAIL, /**< A pairing procedure has failed which means no encryption and no bond could be established. */
SMD_EVT_LINK_ENCRYPTION_UPDATE, /**< The security level of the link has been updated. The link is encrypted. */
SMD_EVT_LINK_ENCRYPTION_FAILED, /**< An attempt to start encryption on an unencrypted link failed because the peripheral did not have the correct keys. If the peer is the peripheral, the force_repairing flag should be set when reattempting @ref smd_link_secure. */
SMD_EVT_BONDING_INFO_STORED, /**< Information exchanged during bonding with a peer has been stored persistently. */
SMD_EVT_ERROR_BONDING_INFO, /**< Information exchanged during bonding with a peer could not be stored persistently, because of an unexpected error. */
// SMD_EVT_ERROR_NO_MEM, /**< An operation failed because there was no available storage room in persistent storage. Please free up room, and the operation will automatically continue. */
SMD_EVT_ERROR_UNEXPECTED, /**< An operation failed with an unexpected error. The error is provided. This is possibly a fatal error. */
} smd_evt_id_t;
/**@brief Events parameters specific to the @ref SMD_EVT_SLAVE_SECURITY_REQ event.
*/
typedef struct
{
bool bond;
bool mitm;
} smd_evt_slave_security_req_t;
/**@brief Events parameters specific to the @ref SMD_EVT_SEC_PROCEDURE_START event.
*/
typedef struct
{
pm_conn_sec_procedure_t procedure; /**< The procedure that has started. */
} smd_evt_sec_procedure_start_t;
/**@brief Events parameters specific to the @ref SMD_EVT_PAIRING_SUCCESS event.
*/
typedef struct
{
bool bonded; /**< Whether bonding was performed. */
bool mitm; /**< Whether MITM protection was used during pairing. */
ble_gap_sec_kdist_t kdist_own; /**< Which keys were distributed to the peer. Only relevant if bonding was performed. */
ble_gap_sec_kdist_t kdist_peer; /**< Which keys were distributed by the peer. Only relevant if bonding was performed. */
} smd_evt_pairing_success_t;
/**@brief Events parameters specific to the @ref SMD_EVT_PAIRING_FAIL event.
*/
typedef struct
{
pm_sec_error_code_t error; /**< What went wrong. */
uint8_t error_src; /**< The party that raised the error, see @ref BLE_GAP_SEC_STATUS_SOURCES. */
} smd_evt_pairing_failed_t;
/**@brief Events parameters specific to the @ref SMD_EVT_LINK_ENCRYPTION_UPDATE event.
*/
typedef struct
{
bool mitm_protected; /**< Whether the link is now MITM protected. */
} smd_evt_link_encryption_update_t;
/**@brief Events parameters specific to the @ref SMD_EVT_LINK_ENCRYPTION_FAILED event.
*/
typedef struct
{
pm_sec_error_code_t error; /**< What went wrong. */
uint8_t error_src; /**< The party that raised the error, see @ref BLE_GAP_SEC_STATUS_SOURCES. */
} smd_evt_link_encryption_failed_t;
/**@brief Events parameters specific to the @ref SMD_EVT_BONDING_INFO_STORED event.
*/
typedef struct
{
pm_peer_id_t peer_id; /**< The peer this event pertains to. */
} smd_evt_bonding_info_stored_t;
/**@brief Events parameters specific to the @ref SMD_EVT_ERROR_BONDING_INFO event.
*/
typedef struct
{
pm_peer_id_t peer_id; /**< The peer this event pertains to, if previously bonded. @ref PM_PEER_ID_INVALID if no successful bonding has happened with the peer before. */
ret_code_t error; /**< The unexpected error that occurred. */
} smd_evt_error_bonding_info_t;
// typedef struct
// {
// pm_peer_id_t peer_id; /**< The peer this event pertains to. */
// } smd_evt_error_no_mem_t;
/**@brief Events parameters specific to the @ref SMD_EVT_ERROR_UNEXPECTED event.
*/
typedef struct
{
ret_code_t error; /**< The unexpected error that occurred. */
} smd_evt_error_unexpected_t;
typedef union
{
smd_evt_slave_security_req_t slave_security_req;
smd_evt_sec_procedure_start_t sec_procedure_start;
smd_evt_pairing_success_t pairing_success;
smd_evt_pairing_failed_t pairing_failed;
smd_evt_link_encryption_update_t link_encryption_update;
smd_evt_link_encryption_failed_t link_encryption_failed;
smd_evt_bonding_info_stored_t bonding_info_stored;
smd_evt_error_bonding_info_t error_bonding_info;
// smd_evt_error_no_mem_t error_no_mem;
smd_evt_error_unexpected_t error_unexpected;
} smd_evt_params_t; /**< Event specific parameters. Chosen based on evt_id. */
/**@brief Structure describing events from the Security Dispatcher module.
*/
typedef struct
{
smd_evt_id_t evt_id; /**< The type of event. */
uint16_t conn_handle; /**< The connection this event pertains to. */
smd_evt_params_t params; /**< Event specific parameters. Chosen based on evt_id. */
} smd_evt_t;
/**@brief Event handler for events from the Security Dispatcher module.
*
* @param[in] p_event The event that has happened.
*/
typedef void (*smd_evt_handler_t)(smd_evt_t const * p_event);
/**@brief Function for registering with the Security Dispatcher module. This function also
* initializes the module if uninitialized.
*
* @param[in] evt_handler Callback for events from the Security Dispatcher module.
*
* @retval NRF_SUCCESS Registration was successful.
* @retval NRF_ERROR_NO_MEM No more registrations possible.
* @retval NRF_ERROR_NULL evt_handler was NULL.
*/
ret_code_t smd_register(smd_evt_handler_t evt_handler);
/**@brief Function for dispatching SoftDevice events to the Security Dispatcher module.
*
* @param[in] ble_evt The SoftDevice event.
*/
void smd_ble_evt_handler(ble_evt_t * ble_evt);
/**@brief Function for providing pairing and bonding parameters to use for the current pairing
* procedure on a connection.
*
* @note If this function returns an @ref NRF_ERROR_NULL, @ref NRF_ERROR_INVALID_PARAM, @ref
* BLE_ERROR_INVALID_CONN_HANDLE, or @ref NRF_ERROR_NO_MEM, this function can be called again
* after corrective action.
*
* @note To reject a request, call this function with NULL p_sec_params.
*
* @param[in] conn_handle The connection handle of the connection the pairing is happening on.
* @param[in] p_sec_params The security parameters to use for this link.
* @param[in] p_public_key A pointer to the public key to use if using LESC, or NULL.
*
* @retval NRF_SUCCESS Success.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized, or no parameters have been
* requested on that conn_handle, or this error originates
* from the SoftDevice.
* @retval NRF_ERROR_INVALID_PARAM Invalid combination of parameters (not including conn_handle).
* @retval NRF_ERROR_TIMEOUT There has been an SMP timeout, so no more SMP operations
* can be performed on this link.
* @retval BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle.
* @retval NRF_ERROR_NO_MEM No more room in flash. Fix and reattempt later.
* @retval NRF_ERROR_BUSY No write buffer. Reattempt later.
*/
ret_code_t smd_params_reply(uint16_t conn_handle,
ble_gap_sec_params_t * p_sec_params,
ble_gap_lesc_p256_pk_t * p_public_key);
/**@brief Function for initiating security on the link, with the specified parameters.
*
* @note If the connection is a peripheral connection, this will send a security request to the
* master, but the master is not obligated to initiate pairing or encryption in response.
* @note If the connection is a central connection and a key is available, the parameters will be
* used to determine whether to re-pair or to encrypt using the existing key. If no key is
* available, pairing will be started.
*
* @param[in] conn_handle Handle of the connection to initiate pairing on.
* @param[in] p_sec_params The security parameters to use for this link. As a central, this can
* be NULL to reject a slave security request.
* @param[in] force_repairing Whether to force a pairing procedure to happen regardless of whether
* an encryption key already exists. This argument is only relevant for
* the central role. Recommended value: false
*
* @retval NRF_SUCCESS Success.
* @retval NRF_ERROR_NULL p_sec_params was NULL (peripheral only).
* @retval NRF_ERROR_INVALID_STATE Module is not initialized, or this error originates from
* the SoftDevice.
* @retval NRF_ERROR_INVALID_PARAM Invalid combination of parameters (not including conn_handle).
* @retval NRF_ERROR_BUSY Unable to initiate procedure at this time.
* @retval NRF_ERROR_TIMEOUT There has been an SMP timeout, so no more SMP operations
* can be performed on this link.
* @retval BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle.
* @retval NRF_ERROR_NO_MEM No more room in flash.
* @retval NRF_ERROR_INTERNAL No more available peer IDs.
*/
ret_code_t smd_link_secure(uint16_t conn_handle,
ble_gap_sec_params_t * p_sec_params,
bool force_repairing);
/** @}
* @endcond
*/
#endif /* SECURITY_DISPATCHER_H__ */

View File

@ -1,580 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 "security_manager.h"
#include <string.h>
#include "security_dispatcher.h"
#include "peer_database.h"
#include "ble_conn_state.h"
#include "sdk_common.h"
#include "id_manager.h"
#define MAX_REGISTRANTS 3 /**< The number of user that can register with the module. */
typedef struct
{
sm_evt_handler_t evt_handlers[MAX_REGISTRANTS];
uint8_t n_registrants;
ble_conn_state_user_flag_id_t flag_id_link_secure_pending_busy;
ble_conn_state_user_flag_id_t flag_id_link_secure_pending_flash_full;
ble_conn_state_user_flag_id_t flag_id_link_secure_force_repairing;
ble_conn_state_user_flag_id_t flag_id_link_secure_null_params;
ble_conn_state_user_flag_id_t flag_id_params_reply_pending_busy;
ble_conn_state_user_flag_id_t flag_id_params_reply_pending_flash_full;
ble_conn_state_user_flag_id_t flag_id_reject_pairing;
bool pdb_evt_handler_registered;
bool sec_params_valid;
ble_gap_sec_params_t sec_params;
ble_gap_lesc_p256_pk_t * p_public_key;
} sm_t;
static sm_t m_sm = {.flag_id_link_secure_pending_busy = BLE_CONN_STATE_USER_FLAG_INVALID,
.flag_id_link_secure_pending_flash_full = BLE_CONN_STATE_USER_FLAG_INVALID,
.flag_id_link_secure_force_repairing = BLE_CONN_STATE_USER_FLAG_INVALID,
.flag_id_link_secure_null_params = BLE_CONN_STATE_USER_FLAG_INVALID,
.flag_id_params_reply_pending_busy = BLE_CONN_STATE_USER_FLAG_INVALID,
.flag_id_params_reply_pending_flash_full = BLE_CONN_STATE_USER_FLAG_INVALID,
.flag_id_reject_pairing = BLE_CONN_STATE_USER_FLAG_INVALID};
#define MODULE_INITIALIZED (m_sm.n_registrants > 0) /**< Expression which is true when the module is initialized. */
#include "sdk_macros.h"
static void evt_send(sm_evt_t * p_event)
{
for (uint32_t i = 0; i < m_sm.n_registrants; i++)
{
m_sm.evt_handlers[i](p_event);
}
}
static void flags_set_from_err_code(uint16_t conn_handle, ret_code_t err_code, bool params_reply)
{
bool flag_value_flash_full = false;
bool flag_value_busy = false;
if ( (err_code == NRF_ERROR_NO_MEM)
|| (err_code == NRF_ERROR_BUSY)
|| (err_code == NRF_SUCCESS))
{
if ((err_code == NRF_ERROR_NO_MEM))
{
flag_value_busy = false;
flag_value_flash_full = true;
}
else if (err_code == NRF_ERROR_BUSY)
{
flag_value_busy = true;
flag_value_flash_full = false;
}
else if (err_code == NRF_SUCCESS)
{
flag_value_busy = false;
flag_value_flash_full = false;
}
if (params_reply)
{
ble_conn_state_user_flag_set(conn_handle,
m_sm.flag_id_params_reply_pending_flash_full,
flag_value_flash_full);
ble_conn_state_user_flag_set(conn_handle,
m_sm.flag_id_params_reply_pending_busy,
flag_value_busy);
ble_conn_state_user_flag_set(conn_handle,
m_sm.flag_id_link_secure_pending_flash_full,
false);
ble_conn_state_user_flag_set(conn_handle,
m_sm.flag_id_link_secure_pending_busy,
false);
}
else
{
ble_conn_state_user_flag_set(conn_handle,
m_sm.flag_id_link_secure_pending_flash_full,
flag_value_flash_full);
ble_conn_state_user_flag_set(conn_handle,
m_sm.flag_id_link_secure_pending_busy,
flag_value_busy);
}
}
}
static void events_send_from_err_code(uint16_t conn_handle, ret_code_t err_code)
{
if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY))
{
sm_evt_t evt =
{
.conn_handle = conn_handle,
.params = {.error_unexpected = {
.error = err_code
}}
};
if (err_code == NRF_ERROR_TIMEOUT)
{
evt.evt_id = SM_EVT_ERROR_SMP_TIMEOUT;
}
else if (err_code == NRF_ERROR_NO_MEM)
{
evt.evt_id = SM_EVT_ERROR_NO_MEM;
}
else
{
evt.evt_id = SM_EVT_ERROR_UNEXPECTED;
}
evt_send(&evt);
}
}
static ret_code_t link_secure(uint16_t conn_handle, bool null_params, bool force_repairing, bool send_events)
{
ret_code_t err_code;
if (!null_params && !m_sm.sec_params_valid)
{
return NRF_ERROR_NOT_FOUND;
}
if(null_params)
{
err_code = smd_link_secure(conn_handle, NULL, force_repairing);
}
else
{
err_code = smd_link_secure(conn_handle, &m_sm.sec_params, force_repairing);
}
flags_set_from_err_code(conn_handle, err_code, false);
if (send_events)
{
events_send_from_err_code(conn_handle, err_code);
}
switch (err_code)
{
case NRF_ERROR_BUSY:
ble_conn_state_user_flag_set(conn_handle, m_sm.flag_id_link_secure_null_params, null_params);
ble_conn_state_user_flag_set(conn_handle, m_sm.flag_id_link_secure_force_repairing, force_repairing);
err_code = NRF_SUCCESS;
break;
case NRF_ERROR_NO_MEM:
ble_conn_state_user_flag_set(conn_handle, m_sm.flag_id_link_secure_null_params, null_params);
ble_conn_state_user_flag_set(conn_handle, m_sm.flag_id_link_secure_force_repairing, force_repairing);
break;
case NRF_SUCCESS:
case NRF_ERROR_TIMEOUT:
case BLE_ERROR_INVALID_CONN_HANDLE:
case NRF_ERROR_INVALID_STATE:
/* No action */
break;
default:
err_code = NRF_ERROR_INTERNAL;
break;
}
return err_code;
}
static void send_config_req(uint16_t conn_handle)
{
sm_evt_t sm_evt;
memset(&sm_evt, 0, sizeof(sm_evt));
sm_evt.evt_id = SM_EVT_CONN_SEC_CONFIG_REQ;
sm_evt.conn_handle = conn_handle;
evt_send(&sm_evt);
}
static void smd_params_reply_perform(uint16_t conn_handle)
{
ret_code_t err_code;
if ( (ble_conn_state_role(conn_handle) == BLE_GAP_ROLE_PERIPH)
&& im_peer_id_get_by_conn_handle(conn_handle) != PM_PEER_ID_INVALID)
{
// Bond already exists. Reject the pairing request if the user doesn't intervene.
ble_conn_state_user_flag_set(conn_handle, m_sm.flag_id_reject_pairing, true);
send_config_req(conn_handle);
}
else
{
ble_conn_state_user_flag_set(conn_handle, m_sm.flag_id_reject_pairing, false);
}
if ( m_sm.sec_params_valid
&& !ble_conn_state_user_flag_get(conn_handle, m_sm.flag_id_reject_pairing))
{
err_code = smd_params_reply(conn_handle, &m_sm.sec_params, m_sm.p_public_key);
}
else
{
err_code = smd_params_reply(conn_handle, NULL, NULL);
}
flags_set_from_err_code(conn_handle, err_code, true);
events_send_from_err_code(conn_handle, err_code);
}
static void smd_evt_handler(smd_evt_t const * p_event)
{
switch(p_event->evt_id)
{
case SMD_EVT_PARAMS_REQ:
smd_params_reply_perform(p_event->conn_handle);
break;
case SMD_EVT_SLAVE_SECURITY_REQ:
{
bool null_params = false;
if (!m_sm.sec_params_valid)
{
null_params = true;
}
else if ((bool)m_sm.sec_params.bond < (bool)p_event->params.slave_security_req.bond)
{
null_params = true;
}
else if ((bool)m_sm.sec_params.mitm < (bool)p_event->params.slave_security_req.mitm)
{
null_params = true;
}
ret_code_t err_code = link_secure(p_event->conn_handle, null_params, false, true);
UNUSED_VARIABLE(err_code); // It is acceptable to ignore the return code because it is
// acceptable to ignore a security request.
}
/* fallthrough */
case SMD_EVT_PAIRING_SUCCESS:
case SMD_EVT_PAIRING_FAIL:
case SMD_EVT_LINK_ENCRYPTION_UPDATE:
case SMD_EVT_LINK_ENCRYPTION_FAILED:
case SMD_EVT_BONDING_INFO_STORED:
case SMD_EVT_ERROR_BONDING_INFO:
case SMD_EVT_ERROR_UNEXPECTED:
case SMD_EVT_SEC_PROCEDURE_START:
{
sm_evt_t evt;
evt.evt_id = (sm_evt_id_t)p_event->evt_id;
evt.conn_handle = p_event->conn_handle;
evt.params = p_event->params;
evt_send(&evt);
}
break;
}
}
static void link_secure_pending_process(ble_conn_state_user_flag_id_t flag_id)
{
sdk_mapped_flags_t flag_collection = ble_conn_state_user_flag_collection(flag_id);
if (sdk_mapped_flags_any_set(flag_collection))
{
sdk_mapped_flags_key_list_t conn_handle_list = ble_conn_state_conn_handles();
for (uint32_t i = 0; i < conn_handle_list.len; i++)
{
bool pending = ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], flag_id);
if (pending)
{
bool force_repairing = ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], m_sm.flag_id_link_secure_force_repairing);
bool null_params = ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], m_sm.flag_id_link_secure_null_params);
ret_code_t err_code = link_secure(conn_handle_list.flag_keys[i], null_params, force_repairing, true); // If this fails, it will be automatically retried.
UNUSED_VARIABLE(err_code);
}
}
}
}
static void params_reply_pending_process(ble_conn_state_user_flag_id_t flag_id)
{
sdk_mapped_flags_t flag_collection = ble_conn_state_user_flag_collection(flag_id);
if (sdk_mapped_flags_any_set(flag_collection))
{
sdk_mapped_flags_key_list_t conn_handle_list = ble_conn_state_conn_handles();
for (uint32_t i = 0; i < conn_handle_list.len; i++)
{
bool pending = ble_conn_state_user_flag_get(conn_handle_list.flag_keys[i], flag_id);
if (pending)
{
smd_params_reply_perform(conn_handle_list.flag_keys[i]);
}
}
}
}
static void pdb_evt_handler(pdb_evt_t const * p_event)
{
switch (p_event->evt_id)
{
case PDB_EVT_COMPRESSED:
params_reply_pending_process(m_sm.flag_id_params_reply_pending_flash_full);
link_secure_pending_process(m_sm.flag_id_link_secure_pending_flash_full);
/* fallthrough */
case PDB_EVT_WRITE_BUF_STORED:
case PDB_EVT_RAW_STORED:
case PDB_EVT_RAW_STORE_FAILED:
case PDB_EVT_CLEARED:
case PDB_EVT_CLEAR_FAILED:
case PDB_EVT_PEER_FREED:
case PDB_EVT_PEER_FREE_FAILED:
params_reply_pending_process(m_sm.flag_id_params_reply_pending_busy);
link_secure_pending_process(m_sm.flag_id_link_secure_pending_busy);
break;
case PDB_EVT_ERROR_NO_MEM:
case PDB_EVT_ERROR_UNEXPECTED:
break;
}
}
/**@brief Funtion for initializing a BLE Connection State user flag.
*
* @param[out] flag_id The flag to initialize.
*/
static void flag_id_init(ble_conn_state_user_flag_id_t * p_flag_id)
{
if (*p_flag_id == BLE_CONN_STATE_USER_FLAG_INVALID)
{
*p_flag_id = ble_conn_state_user_flag_acquire();
}
}
ret_code_t sm_register(sm_evt_handler_t evt_handler)
{
VERIFY_PARAM_NOT_NULL(evt_handler);
ret_code_t err_code = NRF_SUCCESS;
if (!MODULE_INITIALIZED)
{
flag_id_init(&m_sm.flag_id_link_secure_pending_busy);
flag_id_init(&m_sm.flag_id_link_secure_pending_flash_full);
flag_id_init(&m_sm.flag_id_link_secure_force_repairing);
flag_id_init(&m_sm.flag_id_link_secure_null_params);
flag_id_init(&m_sm.flag_id_params_reply_pending_busy);
flag_id_init(&m_sm.flag_id_params_reply_pending_flash_full);
flag_id_init(&m_sm.flag_id_reject_pairing);
if (m_sm.flag_id_reject_pairing == BLE_CONN_STATE_USER_FLAG_INVALID)
{
return NRF_ERROR_INTERNAL;
}
if (!m_sm.pdb_evt_handler_registered)
{
err_code = pdb_register(pdb_evt_handler);
if (err_code != NRF_SUCCESS)
{
return NRF_ERROR_INTERNAL;
}
m_sm.pdb_evt_handler_registered = true;
}
err_code = smd_register(smd_evt_handler);
if (err_code != NRF_SUCCESS)
{
return NRF_ERROR_INTERNAL;
}
}
if (err_code == NRF_SUCCESS)
{
if ((m_sm.n_registrants < MAX_REGISTRANTS))
{
m_sm.evt_handlers[m_sm.n_registrants++] = evt_handler;
}
else
{
err_code = NRF_ERROR_NO_MEM;
}
}
return err_code;
}
void sm_ble_evt_handler(ble_evt_t * p_ble_evt)
{
VERIFY_MODULE_INITIALIZED_VOID();
smd_ble_evt_handler(p_ble_evt);
link_secure_pending_process(m_sm.flag_id_link_secure_pending_busy);
}
static bool sec_params_verify(ble_gap_sec_params_t * p_sec_params)
{
// NULL check.
if (p_sec_params == NULL)
{
return false;
}
// OOB not allowed unless MITM.
if (!p_sec_params->mitm && p_sec_params->oob)
{
return false;
}
// IO Capabilities must be one of the valid values from @ref BLE_GAP_IO_CAPS.
if (p_sec_params->io_caps > BLE_GAP_IO_CAPS_KEYBOARD_DISPLAY)
{
return false;
}
// Must have either IO capabilities or OOB if MITM.
if (p_sec_params->mitm && (p_sec_params->io_caps == BLE_GAP_IO_CAPS_NONE) && !p_sec_params->oob)
{
return false;
}
// Minimum key size cannot be larger than maximum key size.
if (p_sec_params->min_key_size > p_sec_params->max_key_size)
{
return false;
}
// Key size cannot be below 7 bytes.
if (p_sec_params->min_key_size < 7)
{
return false;
}
// Key size cannot be above 16 bytes.
if (p_sec_params->max_key_size > 16)
{
return false;
}
// Signing is not supported.
if (p_sec_params->kdist_own.sign || p_sec_params->kdist_peer.sign)
{
return false;
}
// link bit must be 0.
if (p_sec_params->kdist_own.link || p_sec_params->kdist_peer.link)
{
return false;
}
// If bonding is not enabled, no keys can be distributed.
if (!p_sec_params->bond && ( p_sec_params->kdist_own.enc
|| p_sec_params->kdist_own.id
|| p_sec_params->kdist_peer.enc
|| p_sec_params->kdist_peer.id))
{
return false;
}
// If bonding is enabled, one or more keys must be distributed.
if ( p_sec_params->bond
&& !p_sec_params->kdist_own.enc
&& !p_sec_params->kdist_own.id
&& !p_sec_params->kdist_peer.enc
&& !p_sec_params->kdist_peer.id)
{
return false;
}
return true;
}
ret_code_t sm_sec_params_set(ble_gap_sec_params_t * p_sec_params)
{
VERIFY_MODULE_INITIALIZED();
if (p_sec_params == NULL)
{
m_sm.sec_params_valid = false;
return NRF_SUCCESS;
}
else if (sec_params_verify(p_sec_params))
{
m_sm.sec_params = *p_sec_params;
m_sm.sec_params_valid = true;
return NRF_SUCCESS;
}
else
{
return NRF_ERROR_INVALID_PARAM;
}
}
void sm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config)
{
ble_conn_state_user_flag_set(conn_handle, m_sm.flag_id_reject_pairing, !p_conn_sec_config->allow_repairing);
}
ret_code_t sm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key)
{
VERIFY_MODULE_INITIALIZED();
m_sm.p_public_key = p_public_key;
return NRF_SUCCESS;
}
ret_code_t sm_sec_params_reply(uint16_t conn_handle, ble_gap_sec_params_t * p_sec_params)
{
VERIFY_MODULE_INITIALIZED();
return NRF_SUCCESS;
}
ret_code_t sm_link_secure(uint16_t conn_handle, bool force_repairing)
{
VERIFY_MODULE_INITIALIZED();
ret_code_t err_code = link_secure(conn_handle, false, force_repairing, false);
return err_code;
}

View File

@ -1,219 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 SECURITY_MANAGER_H__
#define SECURITY_MANAGER_H__
#include <stdint.h>
#include "sdk_errors.h"
#include "nrf_ble.h"
#include "nrf_ble_gap.h"
#include "peer_manager_types.h"
#include "security_dispatcher.h"
/**
* @cond NO_DOXYGEN
* @defgroup security_manager Security Manager
* @ingroup peer_manager
* @{
* @brief An internal module of @ref peer_manager. A module for streamlining pairing, bonding, and
* encryption, including flash storage of shared data.
*/
/**@brief Events that can come from the Security Manager module.
*/
typedef enum
{
// SM_EVT_PARAMS_REQ = SMD_EVT_PARAMS_REQ, /**< Parameters are required for a pairing procedure on the specified connection. The user must provide them using @ref sm_sec_params_set or @ref sm_sec_params_reply (only this procedure, currently unimplemented). */
SM_EVT_SLAVE_SECURITY_REQ = SMD_EVT_SLAVE_SECURITY_REQ, /**< The peer (peripheral) has requested link encryption, which has been enabled. */
SM_EVT_SEC_PROCEDURE_START = SMD_EVT_SEC_PROCEDURE_START, /**< A security procedure has started. */
SM_EVT_PAIRING_SUCCESS = SMD_EVT_PAIRING_SUCCESS, /**< A pairing procedure (and bonding if applicable) has completed with success. */
SM_EVT_PAIRING_FAIL = SMD_EVT_PAIRING_FAIL, /**< A pairing procedure has failed which means no encryption and no bond could be established. */
SM_EVT_LINK_ENCRYPTION_UPDATE = SMD_EVT_LINK_ENCRYPTION_UPDATE, /**< The security level of the link has been updated. The link is encrypted. */
SM_EVT_LINK_ENCRYPTION_FAILED = SMD_EVT_LINK_ENCRYPTION_FAILED, /**< An attempt to start encryption on an unencrypted link failed because the peripheral did not have the correct keys. If the peer is the peripheral, the force_repairing flag should be set when reattempting @ref sm_link_secure. */
SM_EVT_BONDING_INFO_STORED = SMD_EVT_BONDING_INFO_STORED, /**< Information exchanged during bonding with a peer has been stored persistently. */
SM_EVT_ERROR_BONDING_INFO = SMD_EVT_ERROR_BONDING_INFO, /**< Information exchanged during bonding with a peer could not be stored persistently, because of an unexpected error. */
SM_EVT_ERROR_UNEXPECTED = SMD_EVT_ERROR_UNEXPECTED, /**< An operation failed with an unexpected error. The error is provided. This is possibly a fatal error. */
SM_EVT_ERROR_NO_MEM /*= SMD_EVT_ERROR_NO_MEM*/, /**< An operation failed because there was no available storage room in persistent storage. Please free up room and the operation will automatically continue after the next compression. */
SM_EVT_ERROR_SMP_TIMEOUT, /**< An operation failed because there has been an SMP timeout on the link, which entails that no more security operations can be performed on it. */
SM_EVT_CONN_SEC_CONFIG_REQ, /**< The peer (central) has requested pairing, but a bond already exists with that peer. Reply by calling @ref sm_conn_sec_config_reply before the event handler returns. If no reply is sent, a default is used. */
} sm_evt_id_t;
typedef struct
{
sm_evt_id_t evt_id;
uint16_t conn_handle;
smd_evt_params_t params;
} sm_evt_t;
/**@brief Event handler for events from the Security Manager module.
*
* @param[in] event The event that has happened.
* @param[in] conn_handle The connection handle the event pertains to.
*/
typedef void (*sm_evt_handler_t)(sm_evt_t const * p_event);
/**@brief Function for registering with the Security Manager module. This function also
* initializes the module if uninitialized.
*
* @param[in] evt_handler Callback for events from the Security Manager module.
*
* @retval NRF_SUCCESS Registration was successful.
* @retval NRF_ERROR_NO_MEM No more registrations possible.
* @retval NRF_ERROR_NULL evt_handler was NULL.
* @retval NRF_ERROR_INTERNAL An unexpected error occurred.
*/
ret_code_t sm_register(sm_evt_handler_t evt_handler);
/**@brief Function for dispatching SoftDevice events to the Security Manager module.
*
* @param[in] ble_evt The SoftDevice event.
*/
void sm_ble_evt_handler(ble_evt_t * ble_evt);
/**@brief Function for providing pairing and bonding parameters to use for pairing procedures.
*
* @details Until this is called, all bonding procedures initiated by the peer will be rejected.
* This function can be called multiple times, even with NULL p_sec_params, in which case
* it will go back to rejecting all procedures.
*
* @param[in] p_sec_params The security parameters to use for this link. Can be NULL to reject
* all pairing procedures.
*
* @retval NRF_SUCCESS Success.
* @retval NRF_ERROR_INVALID_PARAM Invalid combination of parameters.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
*/
ret_code_t sm_sec_params_set(ble_gap_sec_params_t * p_sec_params);
/**@brief Function for providing security configuration for a link.
*
* @details This function is optional, and must be called in reply to a @ref
* SM_EVT_CONN_SEC_CONFIG_REQ event, before the Peer Manager event handler returns. If it
* is not called in time, a default configuration is used. See @ref pm_conn_sec_config_t
* for the value of the default.
*
* @param[in] conn_handle The connection to set the configuration for.
* @param[in] p_conn_sec_config The configuration.
*/
void sm_conn_sec_config_reply(uint16_t conn_handle, pm_conn_sec_config_t * p_conn_sec_config);
/**@brief Experimental function for specifying the public key to use for LESC operations.
*
* @details This function can be called multiple times. The specified public key will be used for
* all subsequent LESC (LE Secure Connections) operations until the next time this function
* is called.
*
* @note The key must continue to reside in application memory as it is not copied by Peer Manager.
*
* @param[in] p_public_key The public key to use for all subsequent LESC operations.
*
* @retval NRF_SUCCESS Pairing initiated successfully.
* @retval NRF_ERROR_INVALID_STATE Peer Manager is not initialized.
*/
ret_code_t sm_lesc_public_key_set(ble_gap_lesc_p256_pk_t * p_public_key);
/**@brief Function for providing pairing and bonding parameters to use for the current pairing
* procedure on a connection.
*
* @warning This function is not yet implemented.
*
* @note If this function returns an @ref NRF_ERROR_NULL, @ref NRF_ERROR_INVALID_PARAM, @ref
* BLE_ERROR_INVALID_CONN_HANDLE, or @ref NRF_ERROR_NO_MEM, this function can be called again
* after corrective action.
*
* @note To reject a request, call this function with NULL p_sec_params.
*
* @param[in] conn_handle The connection handle of the connection the pairing is happening on.
* @param[in] p_sec_params The security parameters to use for this link.
*
* @retval NRF_SUCCESS Success.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized, or no parameters have been
* requested on that conn_handle, or this error originates
* from the SoftDevice.
* @retval NRF_ERROR_INVALID_PARAM Invalid combination of parameters (not including conn_handle).
* @retval NRF_ERROR_TIMEOUT There has been an SMP timeout, so no more SMP operations
* can be performed on this link.
* @retval BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle.
* @retval NRF_ERROR_NO_MEM No more room in flash. Fix and reattempt later.
* @retval NRF_ERROR_BUSY No write buffer. Reattempt later.
*/
ret_code_t sm_sec_params_reply(uint16_t conn_handle, ble_gap_sec_params_t * p_sec_params);
/**@brief Function for initiating security on the link, with the specified parameters.
*
* @note If the connection is a peripheral connection, this will send a security request to the
* master, but the master is not obligated to initiate pairing or encryption in response.
* @note If the connection is a central connection and a key is available, the parameters will be
* used to determine whether to re-pair or to encrypt using the existing key. If no key is
* available, pairing will be started.
*
* @param[in] conn_handle Handle of the connection to initiate pairing on.
* @param[in] force_repairing Whether to force a pairing procedure to happen regardless of whether
* an encryption key already exists. This argument is only relevant for
* the central role. Recommended value: false
*
* @retval NRF_SUCCESS Success.
* @retval NRF_ERROR_TIMEOUT There has been an SMP timeout, so no more SMP operations
* can be performed on this link.
* @retval BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle.
* @retval NRF_ERROR_NOT_FOUND Security parameters have not been set.
* @retval NRF_ERROR_INVALID_STATE Module is not initialized.
* @retval NRF_ERROR_INTERNAL An unexpected error occurred.
*/
ret_code_t sm_link_secure(uint16_t conn_handle, bool force_repairing);
/** @}
* @endcond
*/
#endif /* SECURITY_MANAGER_H__ */

View File

@ -1,135 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 _COMPILER_ABSTRACTION_H
#define _COMPILER_ABSTRACTION_H
/*lint ++flb "Enter library region" */
#if defined ( __CC_ARM )
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE __inline
#endif
#ifndef __WEAK
#define __WEAK __weak
#endif
#ifndef __ALIGN
#define __ALIGN(n) __align(n)
#endif
#define GET_SP() __current_sp()
#elif defined ( __ICCARM__ )
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __WEAK
#define __WEAK __weak
#endif
/* Not defined for IAR since it requires a new line to work, and C preprocessor does not allow that. */
#ifndef __ALIGN
#define __ALIGN(n)
#endif
#define GET_SP() __get_SP()
#elif defined ( __GNUC__ )
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __ALIGN
#define __ALIGN(n) __attribute__((aligned(n)))
#endif
#define GET_SP() gcc_current_sp()
static inline unsigned int gcc_current_sp(void)
{
register unsigned sp __ASM("sp");
return sp;
}
#elif defined ( __TASKING__ )
#ifndef __ASM
#define __ASM __asm
#endif
#ifndef __INLINE
#define __INLINE inline
#endif
#ifndef __WEAK
#define __WEAK __attribute__((weak))
#endif
#ifndef __ALIGN
#define __ALIGN(n) __align(n)
#endif
#define GET_SP() __get_MSP()
#endif
/*lint --flb "Leave library region" */
#endif

View File

@ -1,76 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_H
#define NRF_H
/* MDK version */
#define MDK_MAJOR_VERSION 8
#define MDK_MINOR_VERSION 5
#define MDK_MICRO_VERSION 0
#if defined(_WIN32)
/* Do not include nrf51 specific files when building for PC host */
#elif defined(__unix)
/* Do not include nrf51 specific files when building for PC host */
#elif defined(__APPLE__)
/* Do not include nrf51 specific files when building for PC host */
#else
/* Family selection for family includes. */
#if defined (NRF51)
#include "nrf51.h"
#include "nrf51_bitfields.h"
#include "nrf51_deprecated.h"
#elif defined (NRF52)
#include "nrf52.h"
#include "nrf52_bitfields.h"
#include "nrf51_to_nrf52.h"
#include "nrf52_name_change.h"
#else
#error "Device family must be defined. See nrf.h."
#endif /* NRF51, NRF52 */
#include "compiler_abstraction.h"
#include "irq_handlers_hw.h"
#endif /* _WIN32 || __unix || __APPLE__ */
#endif /* NRF_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,447 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 NRF51_DEPRECATED_H
#define NRF51_DEPRECATED_H
/*lint ++flb "Enter library region */
/* This file is given to prevent your SW from not compiling with the updates made to nrf51.h and
* nrf51_bitfields.h. The macros defined in this file were available previously. Do not use these
* macros on purpose. Use the ones defined in nrf51.h and nrf51_bitfields.h instead.
*/
/* NVMC */
/* The register ERASEPROTECTEDPAGE is called ERASEPCR0 in the documentation. */
#define ERASEPROTECTEDPAGE ERASEPCR0
/* LPCOMP */
/* The interrupt ISR was renamed. Adding old name to the macros. */
#define LPCOMP_COMP_IRQHandler LPCOMP_IRQHandler
#define LPCOMP_COMP_IRQn LPCOMP_IRQn
/* MPU */
/* The field MPU.PERR0.LPCOMP_COMP was renamed. Added into deprecated in case somebody was using the macros defined for it. */
#define MPU_PERR0_LPCOMP_COMP_Pos MPU_PERR0_LPCOMP_Pos
#define MPU_PERR0_LPCOMP_COMP_Msk MPU_PERR0_LPCOMP_Msk
#define MPU_PERR0_LPCOMP_COMP_InRegion1 MPU_PERR0_LPCOMP_InRegion1
#define MPU_PERR0_LPCOMP_COMP_InRegion0 MPU_PERR0_LPCOMP_InRegion0
/* POWER */
/* The field POWER.RAMON.OFFRAM3 was eliminated. Added into deprecated in case somebody was using the macros defined for it. */
#define POWER_RAMON_OFFRAM3_Pos (19UL)
#define POWER_RAMON_OFFRAM3_Msk (0x1UL << POWER_RAMON_OFFRAM3_Pos)
#define POWER_RAMON_OFFRAM3_RAM3Off (0UL)
#define POWER_RAMON_OFFRAM3_RAM3On (1UL)
/* The field POWER.RAMON.OFFRAM2 was eliminated. Added into deprecated in case somebody was using the macros defined for it. */
#define POWER_RAMON_OFFRAM2_Pos (18UL)
#define POWER_RAMON_OFFRAM2_Msk (0x1UL << POWER_RAMON_OFFRAM2_Pos)
#define POWER_RAMON_OFFRAM2_RAM2Off (0UL)
#define POWER_RAMON_OFFRAM2_RAM2On (1UL)
/* The field POWER.RAMON.ONRAM3 was eliminated. Added into deprecated in case somebody was using the macros defined for it. */
#define POWER_RAMON_ONRAM3_Pos (3UL)
#define POWER_RAMON_ONRAM3_Msk (0x1UL << POWER_RAMON_ONRAM3_Pos)
#define POWER_RAMON_ONRAM3_RAM3Off (0UL)
#define POWER_RAMON_ONRAM3_RAM3On (1UL)
/* The field POWER.RAMON.ONRAM2 was eliminated. Added into deprecated in case somebody was using the macros defined for it. */
#define POWER_RAMON_ONRAM2_Pos (2UL)
#define POWER_RAMON_ONRAM2_Msk (0x1UL << POWER_RAMON_ONRAM2_Pos)
#define POWER_RAMON_ONRAM2_RAM2Off (0UL)
#define POWER_RAMON_ONRAM2_RAM2On (1UL)
/* RADIO */
/* The enumerated value RADIO.TXPOWER.TXPOWER.Neg40dBm was renamed. Added into deprecated with the new macro name. */
#define RADIO_TXPOWER_TXPOWER_Neg40dBm RADIO_TXPOWER_TXPOWER_Neg30dBm
/* The name of the field SKIPADDR was corrected. Old macros added for compatibility. */
#define RADIO_CRCCNF_SKIP_ADDR_Pos RADIO_CRCCNF_SKIPADDR_Pos
#define RADIO_CRCCNF_SKIP_ADDR_Msk RADIO_CRCCNF_SKIPADDR_Msk
#define RADIO_CRCCNF_SKIP_ADDR_Include RADIO_CRCCNF_SKIPADDR_Include
#define RADIO_CRCCNF_SKIP_ADDR_Skip RADIO_CRCCNF_SKIPADDR_Skip
/* The name of the field PLLLOCK was corrected. Old macros added for compatibility. */
#define RADIO_TEST_PLL_LOCK_Pos RADIO_TEST_PLLLOCK_Pos
#define RADIO_TEST_PLL_LOCK_Msk RADIO_TEST_PLLLOCK_Msk
#define RADIO_TEST_PLL_LOCK_Disabled RADIO_TEST_PLLLOCK_Disabled
#define RADIO_TEST_PLL_LOCK_Enabled RADIO_TEST_PLLLOCK_Enabled
/* The name of the field CONSTCARRIER was corrected. Old macros added for compatibility. */
#define RADIO_TEST_CONST_CARRIER_Pos RADIO_TEST_CONSTCARRIER_Pos
#define RADIO_TEST_CONST_CARRIER_Msk RADIO_TEST_CONSTCARRIER_Msk
#define RADIO_TEST_CONST_CARRIER_Disabled RADIO_TEST_CONSTCARRIER_Disabled
#define RADIO_TEST_CONST_CARRIER_Enabled RADIO_TEST_CONSTCARRIER_Enabled
/* FICR */
/* The registers FICR.SIZERAMBLOCK0, FICR.SIZERAMBLOCK1, FICR.SIZERAMBLOCK2 and FICR.SIZERAMBLOCK3 were renamed into an array. */
#define SIZERAMBLOCK0 SIZERAMBLOCKS
#define SIZERAMBLOCK1 SIZERAMBLOCKS
#define SIZERAMBLOCK2 SIZERAMBLOCK[2] /*!< Note that this macro will disapear when SIZERAMBLOCK array is eliminated. SIZERAMBLOCK is a deprecated array. */
#define SIZERAMBLOCK3 SIZERAMBLOCK[3] /*!< Note that this macro will disapear when SIZERAMBLOCK array is eliminated. SIZERAMBLOCK is a deprecated array. */
/* The registers FICR.DEVICEID0 and FICR.DEVICEID1 were renamed into an array. */
#define DEVICEID0 DEVICEID[0]
#define DEVICEID1 DEVICEID[1]
/* The registers FICR.ER0, FICR.ER1, FICR.ER2 and FICR.ER3 were renamed into an array. */
#define ER0 ER[0]
#define ER1 ER[1]
#define ER2 ER[2]
#define ER3 ER[3]
/* The registers FICR.IR0, FICR.IR1, FICR.IR2 and FICR.IR3 were renamed into an array. */
#define IR0 IR[0]
#define IR1 IR[1]
#define IR2 IR[2]
#define IR3 IR[3]
/* The registers FICR.DEVICEADDR0 and FICR.DEVICEADDR1 were renamed into an array. */
#define DEVICEADDR0 DEVICEADDR[0]
#define DEVICEADDR1 DEVICEADDR[1]
/* PPI */
/* The tasks PPI.TASKS_CHGxEN and PPI.TASKS_CHGxDIS were renamed into an array of structs. */
#define TASKS_CHG0EN TASKS_CHG[0].EN
#define TASKS_CHG0DIS TASKS_CHG[0].DIS
#define TASKS_CHG1EN TASKS_CHG[1].EN
#define TASKS_CHG1DIS TASKS_CHG[1].DIS
#define TASKS_CHG2EN TASKS_CHG[2].EN
#define TASKS_CHG2DIS TASKS_CHG[2].DIS
#define TASKS_CHG3EN TASKS_CHG[3].EN
#define TASKS_CHG3DIS TASKS_CHG[3].DIS
/* The registers PPI.CHx_EEP and PPI.CHx_TEP were renamed into an array of structs. */
#define CH0_EEP CH[0].EEP
#define CH0_TEP CH[0].TEP
#define CH1_EEP CH[1].EEP
#define CH1_TEP CH[1].TEP
#define CH2_EEP CH[2].EEP
#define CH2_TEP CH[2].TEP
#define CH3_EEP CH[3].EEP
#define CH3_TEP CH[3].TEP
#define CH4_EEP CH[4].EEP
#define CH4_TEP CH[4].TEP
#define CH5_EEP CH[5].EEP
#define CH5_TEP CH[5].TEP
#define CH6_EEP CH[6].EEP
#define CH6_TEP CH[6].TEP
#define CH7_EEP CH[7].EEP
#define CH7_TEP CH[7].TEP
#define CH8_EEP CH[8].EEP
#define CH8_TEP CH[8].TEP
#define CH9_EEP CH[9].EEP
#define CH9_TEP CH[9].TEP
#define CH10_EEP CH[10].EEP
#define CH10_TEP CH[10].TEP
#define CH11_EEP CH[11].EEP
#define CH11_TEP CH[11].TEP
#define CH12_EEP CH[12].EEP
#define CH12_TEP CH[12].TEP
#define CH13_EEP CH[13].EEP
#define CH13_TEP CH[13].TEP
#define CH14_EEP CH[14].EEP
#define CH14_TEP CH[14].TEP
#define CH15_EEP CH[15].EEP
#define CH15_TEP CH[15].TEP
/* The registers PPI.CHG0, PPI.CHG1, PPI.CHG2 and PPI.CHG3 were renamed into an array. */
#define CHG0 CHG[0]
#define CHG1 CHG[1]
#define CHG2 CHG[2]
#define CHG3 CHG[3]
/* All bitfield macros for the CHGx registers therefore changed name. */
#define PPI_CHG0_CH15_Pos PPI_CHG_CH15_Pos
#define PPI_CHG0_CH15_Msk PPI_CHG_CH15_Msk
#define PPI_CHG0_CH15_Excluded PPI_CHG_CH15_Excluded
#define PPI_CHG0_CH15_Included PPI_CHG_CH15_Included
#define PPI_CHG0_CH14_Pos PPI_CHG_CH14_Pos
#define PPI_CHG0_CH14_Msk PPI_CHG_CH14_Msk
#define PPI_CHG0_CH14_Excluded PPI_CHG_CH14_Excluded
#define PPI_CHG0_CH14_Included PPI_CHG_CH14_Included
#define PPI_CHG0_CH13_Pos PPI_CHG_CH13_Pos
#define PPI_CHG0_CH13_Msk PPI_CHG_CH13_Msk
#define PPI_CHG0_CH13_Excluded PPI_CHG_CH13_Excluded
#define PPI_CHG0_CH13_Included PPI_CHG_CH13_Included
#define PPI_CHG0_CH12_Pos PPI_CHG_CH12_Pos
#define PPI_CHG0_CH12_Msk PPI_CHG_CH12_Msk
#define PPI_CHG0_CH12_Excluded PPI_CHG_CH12_Excluded
#define PPI_CHG0_CH12_Included PPI_CHG_CH12_Included
#define PPI_CHG0_CH11_Pos PPI_CHG_CH11_Pos
#define PPI_CHG0_CH11_Msk PPI_CHG_CH11_Msk
#define PPI_CHG0_CH11_Excluded PPI_CHG_CH11_Excluded
#define PPI_CHG0_CH11_Included PPI_CHG_CH11_Included
#define PPI_CHG0_CH10_Pos PPI_CHG_CH10_Pos
#define PPI_CHG0_CH10_Msk PPI_CHG_CH10_Msk
#define PPI_CHG0_CH10_Excluded PPI_CHG_CH10_Excluded
#define PPI_CHG0_CH10_Included PPI_CHG_CH10_Included
#define PPI_CHG0_CH9_Pos PPI_CHG_CH9_Pos
#define PPI_CHG0_CH9_Msk PPI_CHG_CH9_Msk
#define PPI_CHG0_CH9_Excluded PPI_CHG_CH9_Excluded
#define PPI_CHG0_CH9_Included PPI_CHG_CH9_Included
#define PPI_CHG0_CH8_Pos PPI_CHG_CH8_Pos
#define PPI_CHG0_CH8_Msk PPI_CHG_CH8_Msk
#define PPI_CHG0_CH8_Excluded PPI_CHG_CH8_Excluded
#define PPI_CHG0_CH8_Included PPI_CHG_CH8_Included
#define PPI_CHG0_CH7_Pos PPI_CHG_CH7_Pos
#define PPI_CHG0_CH7_Msk PPI_CHG_CH7_Msk
#define PPI_CHG0_CH7_Excluded PPI_CHG_CH7_Excluded
#define PPI_CHG0_CH7_Included PPI_CHG_CH7_Included
#define PPI_CHG0_CH6_Pos PPI_CHG_CH6_Pos
#define PPI_CHG0_CH6_Msk PPI_CHG_CH6_Msk
#define PPI_CHG0_CH6_Excluded PPI_CHG_CH6_Excluded
#define PPI_CHG0_CH6_Included PPI_CHG_CH6_Included
#define PPI_CHG0_CH5_Pos PPI_CHG_CH5_Pos
#define PPI_CHG0_CH5_Msk PPI_CHG_CH5_Msk
#define PPI_CHG0_CH5_Excluded PPI_CHG_CH5_Excluded
#define PPI_CHG0_CH5_Included PPI_CHG_CH5_Included
#define PPI_CHG0_CH4_Pos PPI_CHG_CH4_Pos
#define PPI_CHG0_CH4_Msk PPI_CHG_CH4_Msk
#define PPI_CHG0_CH4_Excluded PPI_CHG_CH4_Excluded
#define PPI_CHG0_CH4_Included PPI_CHG_CH4_Included
#define PPI_CHG0_CH3_Pos PPI_CHG_CH3_Pos
#define PPI_CHG0_CH3_Msk PPI_CHG_CH3_Msk
#define PPI_CHG0_CH3_Excluded PPI_CHG_CH3_Excluded
#define PPI_CHG0_CH3_Included PPI_CHG_CH3_Included
#define PPI_CHG0_CH2_Pos PPI_CHG_CH2_Pos
#define PPI_CHG0_CH2_Msk PPI_CHG_CH2_Msk
#define PPI_CHG0_CH2_Excluded PPI_CHG_CH2_Excluded
#define PPI_CHG0_CH2_Included PPI_CHG_CH2_Included
#define PPI_CHG0_CH1_Pos PPI_CHG_CH1_Pos
#define PPI_CHG0_CH1_Msk PPI_CHG_CH1_Msk
#define PPI_CHG0_CH1_Excluded PPI_CHG_CH1_Excluded
#define PPI_CHG0_CH1_Included PPI_CHG_CH1_Included
#define PPI_CHG0_CH0_Pos PPI_CHG_CH0_Pos
#define PPI_CHG0_CH0_Msk PPI_CHG_CH0_Msk
#define PPI_CHG0_CH0_Excluded PPI_CHG_CH0_Excluded
#define PPI_CHG0_CH0_Included PPI_CHG_CH0_Included
#define PPI_CHG1_CH15_Pos PPI_CHG_CH15_Pos
#define PPI_CHG1_CH15_Msk PPI_CHG_CH15_Msk
#define PPI_CHG1_CH15_Excluded PPI_CHG_CH15_Excluded
#define PPI_CHG1_CH15_Included PPI_CHG_CH15_Included
#define PPI_CHG1_CH14_Pos PPI_CHG_CH14_Pos
#define PPI_CHG1_CH14_Msk PPI_CHG_CH14_Msk
#define PPI_CHG1_CH14_Excluded PPI_CHG_CH14_Excluded
#define PPI_CHG1_CH14_Included PPI_CHG_CH14_Included
#define PPI_CHG1_CH13_Pos PPI_CHG_CH13_Pos
#define PPI_CHG1_CH13_Msk PPI_CHG_CH13_Msk
#define PPI_CHG1_CH13_Excluded PPI_CHG_CH13_Excluded
#define PPI_CHG1_CH13_Included PPI_CHG_CH13_Included
#define PPI_CHG1_CH12_Pos PPI_CHG_CH12_Pos
#define PPI_CHG1_CH12_Msk PPI_CHG_CH12_Msk
#define PPI_CHG1_CH12_Excluded PPI_CHG_CH12_Excluded
#define PPI_CHG1_CH12_Included PPI_CHG_CH12_Included
#define PPI_CHG1_CH11_Pos PPI_CHG_CH11_Pos
#define PPI_CHG1_CH11_Msk PPI_CHG_CH11_Msk
#define PPI_CHG1_CH11_Excluded PPI_CHG_CH11_Excluded
#define PPI_CHG1_CH11_Included PPI_CHG_CH11_Included
#define PPI_CHG1_CH10_Pos PPI_CHG_CH10_Pos
#define PPI_CHG1_CH10_Msk PPI_CHG_CH10_Msk
#define PPI_CHG1_CH10_Excluded PPI_CHG_CH10_Excluded
#define PPI_CHG1_CH10_Included PPI_CHG_CH10_Included
#define PPI_CHG1_CH9_Pos PPI_CHG_CH9_Pos
#define PPI_CHG1_CH9_Msk PPI_CHG_CH9_Msk
#define PPI_CHG1_CH9_Excluded PPI_CHG_CH9_Excluded
#define PPI_CHG1_CH9_Included PPI_CHG_CH9_Included
#define PPI_CHG1_CH8_Pos PPI_CHG_CH8_Pos
#define PPI_CHG1_CH8_Msk PPI_CHG_CH8_Msk
#define PPI_CHG1_CH8_Excluded PPI_CHG_CH8_Excluded
#define PPI_CHG1_CH8_Included PPI_CHG_CH8_Included
#define PPI_CHG1_CH7_Pos PPI_CHG_CH7_Pos
#define PPI_CHG1_CH7_Msk PPI_CHG_CH7_Msk
#define PPI_CHG1_CH7_Excluded PPI_CHG_CH7_Excluded
#define PPI_CHG1_CH7_Included PPI_CHG_CH7_Included
#define PPI_CHG1_CH6_Pos PPI_CHG_CH6_Pos
#define PPI_CHG1_CH6_Msk PPI_CHG_CH6_Msk
#define PPI_CHG1_CH6_Excluded PPI_CHG_CH6_Excluded
#define PPI_CHG1_CH6_Included PPI_CHG_CH6_Included
#define PPI_CHG1_CH5_Pos PPI_CHG_CH5_Pos
#define PPI_CHG1_CH5_Msk PPI_CHG_CH5_Msk
#define PPI_CHG1_CH5_Excluded PPI_CHG_CH5_Excluded
#define PPI_CHG1_CH5_Included PPI_CHG_CH5_Included
#define PPI_CHG1_CH4_Pos PPI_CHG_CH4_Pos
#define PPI_CHG1_CH4_Msk PPI_CHG_CH4_Msk
#define PPI_CHG1_CH4_Excluded PPI_CHG_CH4_Excluded
#define PPI_CHG1_CH4_Included PPI_CHG_CH4_Included
#define PPI_CHG1_CH3_Pos PPI_CHG_CH3_Pos
#define PPI_CHG1_CH3_Msk PPI_CHG_CH3_Msk
#define PPI_CHG1_CH3_Excluded PPI_CHG_CH3_Excluded
#define PPI_CHG1_CH3_Included PPI_CHG_CH3_Included
#define PPI_CHG1_CH2_Pos PPI_CHG_CH2_Pos
#define PPI_CHG1_CH2_Msk PPI_CHG_CH2_Msk
#define PPI_CHG1_CH2_Excluded PPI_CHG_CH2_Excluded
#define PPI_CHG1_CH2_Included PPI_CHG_CH2_Included
#define PPI_CHG1_CH1_Pos PPI_CHG_CH1_Pos
#define PPI_CHG1_CH1_Msk PPI_CHG_CH1_Msk
#define PPI_CHG1_CH1_Excluded PPI_CHG_CH1_Excluded
#define PPI_CHG1_CH1_Included PPI_CHG_CH1_Included
#define PPI_CHG1_CH0_Pos PPI_CHG_CH0_Pos
#define PPI_CHG1_CH0_Msk PPI_CHG_CH0_Msk
#define PPI_CHG1_CH0_Excluded PPI_CHG_CH0_Excluded
#define PPI_CHG1_CH0_Included PPI_CHG_CH0_Included
#define PPI_CHG2_CH15_Pos PPI_CHG_CH15_Pos
#define PPI_CHG2_CH15_Msk PPI_CHG_CH15_Msk
#define PPI_CHG2_CH15_Excluded PPI_CHG_CH15_Excluded
#define PPI_CHG2_CH15_Included PPI_CHG_CH15_Included
#define PPI_CHG2_CH14_Pos PPI_CHG_CH14_Pos
#define PPI_CHG2_CH14_Msk PPI_CHG_CH14_Msk
#define PPI_CHG2_CH14_Excluded PPI_CHG_CH14_Excluded
#define PPI_CHG2_CH14_Included PPI_CHG_CH14_Included
#define PPI_CHG2_CH13_Pos PPI_CHG_CH13_Pos
#define PPI_CHG2_CH13_Msk PPI_CHG_CH13_Msk
#define PPI_CHG2_CH13_Excluded PPI_CHG_CH13_Excluded
#define PPI_CHG2_CH13_Included PPI_CHG_CH13_Included
#define PPI_CHG2_CH12_Pos PPI_CHG_CH12_Pos
#define PPI_CHG2_CH12_Msk PPI_CHG_CH12_Msk
#define PPI_CHG2_CH12_Excluded PPI_CHG_CH12_Excluded
#define PPI_CHG2_CH12_Included PPI_CHG_CH12_Included
#define PPI_CHG2_CH11_Pos PPI_CHG_CH11_Pos
#define PPI_CHG2_CH11_Msk PPI_CHG_CH11_Msk
#define PPI_CHG2_CH11_Excluded PPI_CHG_CH11_Excluded
#define PPI_CHG2_CH11_Included PPI_CHG_CH11_Included
#define PPI_CHG2_CH10_Pos PPI_CHG_CH10_Pos
#define PPI_CHG2_CH10_Msk PPI_CHG_CH10_Msk
#define PPI_CHG2_CH10_Excluded PPI_CHG_CH10_Excluded
#define PPI_CHG2_CH10_Included PPI_CHG_CH10_Included
#define PPI_CHG2_CH9_Pos PPI_CHG_CH9_Pos
#define PPI_CHG2_CH9_Msk PPI_CHG_CH9_Msk
#define PPI_CHG2_CH9_Excluded PPI_CHG_CH9_Excluded
#define PPI_CHG2_CH9_Included PPI_CHG_CH9_Included
#define PPI_CHG2_CH8_Pos PPI_CHG_CH8_Pos
#define PPI_CHG2_CH8_Msk PPI_CHG_CH8_Msk
#define PPI_CHG2_CH8_Excluded PPI_CHG_CH8_Excluded
#define PPI_CHG2_CH8_Included PPI_CHG_CH8_Included
#define PPI_CHG2_CH7_Pos PPI_CHG_CH7_Pos
#define PPI_CHG2_CH7_Msk PPI_CHG_CH7_Msk
#define PPI_CHG2_CH7_Excluded PPI_CHG_CH7_Excluded
#define PPI_CHG2_CH7_Included PPI_CHG_CH7_Included
#define PPI_CHG2_CH6_Pos PPI_CHG_CH6_Pos
#define PPI_CHG2_CH6_Msk PPI_CHG_CH6_Msk
#define PPI_CHG2_CH6_Excluded PPI_CHG_CH6_Excluded
#define PPI_CHG2_CH6_Included PPI_CHG_CH6_Included
#define PPI_CHG2_CH5_Pos PPI_CHG_CH5_Pos
#define PPI_CHG2_CH5_Msk PPI_CHG_CH5_Msk
#define PPI_CHG2_CH5_Excluded PPI_CHG_CH5_Excluded
#define PPI_CHG2_CH5_Included PPI_CHG_CH5_Included
#define PPI_CHG2_CH4_Pos PPI_CHG_CH4_Pos
#define PPI_CHG2_CH4_Msk PPI_CHG_CH4_Msk
#define PPI_CHG2_CH4_Excluded PPI_CHG_CH4_Excluded
#define PPI_CHG2_CH4_Included PPI_CHG_CH4_Included
#define PPI_CHG2_CH3_Pos PPI_CHG_CH3_Pos
#define PPI_CHG2_CH3_Msk PPI_CHG_CH3_Msk
#define PPI_CHG2_CH3_Excluded PPI_CHG_CH3_Excluded
#define PPI_CHG2_CH3_Included PPI_CHG_CH3_Included
#define PPI_CHG2_CH2_Pos PPI_CHG_CH2_Pos
#define PPI_CHG2_CH2_Msk PPI_CHG_CH2_Msk
#define PPI_CHG2_CH2_Excluded PPI_CHG_CH2_Excluded
#define PPI_CHG2_CH2_Included PPI_CHG_CH2_Included
#define PPI_CHG2_CH1_Pos PPI_CHG_CH1_Pos
#define PPI_CHG2_CH1_Msk PPI_CHG_CH1_Msk
#define PPI_CHG2_CH1_Excluded PPI_CHG_CH1_Excluded
#define PPI_CHG2_CH1_Included PPI_CHG_CH1_Included
#define PPI_CHG2_CH0_Pos PPI_CHG_CH0_Pos
#define PPI_CHG2_CH0_Msk PPI_CHG_CH0_Msk
#define PPI_CHG2_CH0_Excluded PPI_CHG_CH0_Excluded
#define PPI_CHG2_CH0_Included PPI_CHG_CH0_Included
#define PPI_CHG3_CH15_Pos PPI_CHG_CH15_Pos
#define PPI_CHG3_CH15_Msk PPI_CHG_CH15_Msk
#define PPI_CHG3_CH15_Excluded PPI_CHG_CH15_Excluded
#define PPI_CHG3_CH15_Included PPI_CHG_CH15_Included
#define PPI_CHG3_CH14_Pos PPI_CHG_CH14_Pos
#define PPI_CHG3_CH14_Msk PPI_CHG_CH14_Msk
#define PPI_CHG3_CH14_Excluded PPI_CHG_CH14_Excluded
#define PPI_CHG3_CH14_Included PPI_CHG_CH14_Included
#define PPI_CHG3_CH13_Pos PPI_CHG_CH13_Pos
#define PPI_CHG3_CH13_Msk PPI_CHG_CH13_Msk
#define PPI_CHG3_CH13_Excluded PPI_CHG_CH13_Excluded
#define PPI_CHG3_CH13_Included PPI_CHG_CH13_Included
#define PPI_CHG3_CH12_Pos PPI_CHG_CH12_Pos
#define PPI_CHG3_CH12_Msk PPI_CHG_CH12_Msk
#define PPI_CHG3_CH12_Excluded PPI_CHG_CH12_Excluded
#define PPI_CHG3_CH12_Included PPI_CHG_CH12_Included
#define PPI_CHG3_CH11_Pos PPI_CHG_CH11_Pos
#define PPI_CHG3_CH11_Msk PPI_CHG_CH11_Msk
#define PPI_CHG3_CH11_Excluded PPI_CHG_CH11_Excluded
#define PPI_CHG3_CH11_Included PPI_CHG_CH11_Included
#define PPI_CHG3_CH10_Pos PPI_CHG_CH10_Pos
#define PPI_CHG3_CH10_Msk PPI_CHG_CH10_Msk
#define PPI_CHG3_CH10_Excluded PPI_CHG_CH10_Excluded
#define PPI_CHG3_CH10_Included PPI_CHG_CH10_Included
#define PPI_CHG3_CH9_Pos PPI_CHG_CH9_Pos
#define PPI_CHG3_CH9_Msk PPI_CHG_CH9_Msk
#define PPI_CHG3_CH9_Excluded PPI_CHG_CH9_Excluded
#define PPI_CHG3_CH9_Included PPI_CHG_CH9_Included
#define PPI_CHG3_CH8_Pos PPI_CHG_CH8_Pos
#define PPI_CHG3_CH8_Msk PPI_CHG_CH8_Msk
#define PPI_CHG3_CH8_Excluded PPI_CHG_CH8_Excluded
#define PPI_CHG3_CH8_Included PPI_CHG_CH8_Included
#define PPI_CHG3_CH7_Pos PPI_CHG_CH7_Pos
#define PPI_CHG3_CH7_Msk PPI_CHG_CH7_Msk
#define PPI_CHG3_CH7_Excluded PPI_CHG_CH7_Excluded
#define PPI_CHG3_CH7_Included PPI_CHG_CH7_Included
#define PPI_CHG3_CH6_Pos PPI_CHG_CH6_Pos
#define PPI_CHG3_CH6_Msk PPI_CHG_CH6_Msk
#define PPI_CHG3_CH6_Excluded PPI_CHG_CH6_Excluded
#define PPI_CHG3_CH6_Included PPI_CHG_CH6_Included
#define PPI_CHG3_CH5_Pos PPI_CHG_CH5_Pos
#define PPI_CHG3_CH5_Msk PPI_CHG_CH5_Msk
#define PPI_CHG3_CH5_Excluded PPI_CHG_CH5_Excluded
#define PPI_CHG3_CH5_Included PPI_CHG_CH5_Included
#define PPI_CHG3_CH4_Pos PPI_CHG_CH4_Pos
#define PPI_CHG3_CH4_Msk PPI_CHG_CH4_Msk
#define PPI_CHG3_CH4_Excluded PPI_CHG_CH4_Excluded
#define PPI_CHG3_CH4_Included PPI_CHG_CH4_Included
#define PPI_CHG3_CH3_Pos PPI_CHG_CH3_Pos
#define PPI_CHG3_CH3_Msk PPI_CHG_CH3_Msk
#define PPI_CHG3_CH3_Excluded PPI_CHG_CH3_Excluded
#define PPI_CHG3_CH3_Included PPI_CHG_CH3_Included
#define PPI_CHG3_CH2_Pos PPI_CHG_CH2_Pos
#define PPI_CHG3_CH2_Msk PPI_CHG_CH2_Msk
#define PPI_CHG3_CH2_Excluded PPI_CHG_CH2_Excluded
#define PPI_CHG3_CH2_Included PPI_CHG_CH2_Included
#define PPI_CHG3_CH1_Pos PPI_CHG_CH1_Pos
#define PPI_CHG3_CH1_Msk PPI_CHG_CH1_Msk
#define PPI_CHG3_CH1_Excluded PPI_CHG_CH1_Excluded
#define PPI_CHG3_CH1_Included PPI_CHG_CH1_Included
#define PPI_CHG3_CH0_Pos PPI_CHG_CH0_Pos
#define PPI_CHG3_CH0_Msk PPI_CHG_CH0_Msk
#define PPI_CHG3_CH0_Excluded PPI_CHG_CH0_Excluded
#define PPI_CHG3_CH0_Included PPI_CHG_CH0_Included
/*lint --flb "Leave library region" */
#endif /* NRF51_DEPRECATED_H */

View File

@ -1,944 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 NRF51_TO_NRF52_H
#define NRF51_TO_NRF52_H
/*lint ++flb "Enter library region */
/* This file is given to prevent your SW from not compiling with the name changes between nRF51 and nRF52 devices.
* It redefines the old nRF51 names into the new ones as long as the functionality is still supported. If the
* functionality is gone, there old names are not define, so compilation will fail. Note that also includes macros
* from the nrf51_deprecated.h file. */
/* IRQ */
/* Several peripherals have been added to several indexes. Names of IRQ handlers and IRQ numbers have changed. */
#define UART0_IRQHandler UARTE0_UART0_IRQHandler
#define SPI0_TWI0_IRQHandler SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler
#define SPI1_TWI1_IRQHandler SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler
#define ADC_IRQHandler SAADC_IRQHandler
#define LPCOMP_IRQHandler COMP_LPCOMP_IRQHandler
#define SWI0_IRQHandler SWI0_EGU0_IRQHandler
#define SWI1_IRQHandler SWI1_EGU1_IRQHandler
#define SWI2_IRQHandler SWI2_EGU2_IRQHandler
#define SWI3_IRQHandler SWI3_EGU3_IRQHandler
#define SWI4_IRQHandler SWI4_EGU4_IRQHandler
#define SWI5_IRQHandler SWI5_EGU5_IRQHandler
#define UART0_IRQn UARTE0_UART0_IRQn
#define SPI0_TWI0_IRQn SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn
#define SPI1_TWI1_IRQn SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn
#define ADC_IRQn SAADC_IRQn
#define LPCOMP_IRQn COMP_LPCOMP_IRQn
#define SWI0_IRQn SWI0_EGU0_IRQn
#define SWI1_IRQn SWI1_EGU1_IRQn
#define SWI2_IRQn SWI2_EGU2_IRQn
#define SWI3_IRQn SWI3_EGU3_IRQn
#define SWI4_IRQn SWI4_EGU4_IRQn
#define SWI5_IRQn SWI5_EGU5_IRQn
/* UICR */
/* Register RBPCONF was renamed to APPROTECT. */
#define RBPCONF APPROTECT
#define UICR_RBPCONF_PALL_Pos UICR_APPROTECT_PALL_Pos
#define UICR_RBPCONF_PALL_Msk UICR_APPROTECT_PALL_Msk
#define UICR_RBPCONF_PALL_Enabled UICR_APPROTECT_PALL_Enabled
#define UICR_RBPCONF_PALL_Disabled UICR_APPROTECT_PALL_Disabled
/* GPIO */
/* GPIO port was renamed to P0. */
#define NRF_GPIO NRF_P0
#define NRF_GPIO_BASE NRF_P0_BASE
/* SPIS */
/* The registers PSELSCK, PSELMISO, PSELMOSI, PSELCSN were restructured into a struct. */
#define PSELSCK PSEL.SCK
#define PSELMISO PSEL.MISO
#define PSELMOSI PSEL.MOSI
#define PSELCSN PSEL.CSN
/* The registers RXDPTR, MAXRX, AMOUNTRX were restructured into a struct */
#define RXDPTR RXD.PTR
#define MAXRX RXD.MAXCNT
#define AMOUNTRX RXD.AMOUNT
#define SPIS_MAXRX_MAXRX_Pos SPIS_RXD_MAXCNT_MAXCNT_Pos
#define SPIS_MAXRX_MAXRX_Msk SPIS_RXD_MAXCNT_MAXCNT_Msk
#define SPIS_AMOUNTRX_AMOUNTRX_Pos SPIS_RXD_AMOUNT_AMOUNT_Pos
#define SPIS_AMOUNTRX_AMOUNTRX_Msk SPIS_RXD_AMOUNT_AMOUNT_Msk
/* The registers TXDPTR, MAXTX, AMOUNTTX were restructured into a struct */
#define TXDPTR TXD.PTR
#define MAXTX TXD.MAXCNT
#define AMOUNTTX TXD.AMOUNT
#define SPIS_MAXTX_MAXTX_Pos SPIS_TXD_MAXCNT_MAXCNT_Pos
#define SPIS_MAXTX_MAXTX_Msk SPIS_TXD_MAXCNT_MAXCNT_Msk
#define SPIS_AMOUNTTX_AMOUNTTX_Pos SPIS_TXD_AMOUNT_AMOUNT_Pos
#define SPIS_AMOUNTTX_AMOUNTTX_Msk SPIS_TXD_AMOUNT_AMOUNT_Msk
/* MPU */
/* Part of MPU module was renamed BPROT, while the rest was eliminated. */
#define NRF_MPU NRF_BPROT
/* Register DISABLEINDEBUG macros were affected. */
#define MPU_DISABLEINDEBUG_DISABLEINDEBUG_Pos BPROT_DISABLEINDEBUG_DISABLEINDEBUG_Pos
#define MPU_DISABLEINDEBUG_DISABLEINDEBUG_Msk BPROT_DISABLEINDEBUG_DISABLEINDEBUG_Msk
#define MPU_DISABLEINDEBUG_DISABLEINDEBUG_Enabled BPROT_DISABLEINDEBUG_DISABLEINDEBUG_Enabled
#define MPU_DISABLEINDEBUG_DISABLEINDEBUG_Disabled BPROT_DISABLEINDEBUG_DISABLEINDEBUG_Disabled
/* Registers PROTENSET0 and PROTENSET1 were affected and renamed as CONFIG0 and CONFIG1. */
#define PROTENSET0 CONFIG0
#define PROTENSET1 CONFIG1
#define MPU_PROTENSET1_PROTREG63_Pos BPROT_CONFIG1_REGION63_Pos
#define MPU_PROTENSET1_PROTREG63_Msk BPROT_CONFIG1_REGION63_Msk
#define MPU_PROTENSET1_PROTREG63_Disabled BPROT_CONFIG1_REGION63_Disabled
#define MPU_PROTENSET1_PROTREG63_Enabled BPROT_CONFIG1_REGION63_Enabled
#define MPU_PROTENSET1_PROTREG63_Set BPROT_CONFIG1_REGION63_Enabled
#define MPU_PROTENSET1_PROTREG62_Pos BPROT_CONFIG1_REGION62_Pos
#define MPU_PROTENSET1_PROTREG62_Msk BPROT_CONFIG1_REGION62_Msk
#define MPU_PROTENSET1_PROTREG62_Disabled BPROT_CONFIG1_REGION62_Disabled
#define MPU_PROTENSET1_PROTREG62_Enabled BPROT_CONFIG1_REGION62_Enabled
#define MPU_PROTENSET1_PROTREG62_Set BPROT_CONFIG1_REGION62_Enabled
#define MPU_PROTENSET1_PROTREG61_Pos BPROT_CONFIG1_REGION61_Pos
#define MPU_PROTENSET1_PROTREG61_Msk BPROT_CONFIG1_REGION61_Msk
#define MPU_PROTENSET1_PROTREG61_Disabled BPROT_CONFIG1_REGION61_Disabled
#define MPU_PROTENSET1_PROTREG61_Enabled BPROT_CONFIG1_REGION61_Enabled
#define MPU_PROTENSET1_PROTREG61_Set BPROT_CONFIG1_REGION61_Enabled
#define MPU_PROTENSET1_PROTREG60_Pos BPROT_CONFIG1_REGION60_Pos
#define MPU_PROTENSET1_PROTREG60_Msk BPROT_CONFIG1_REGION60_Msk
#define MPU_PROTENSET1_PROTREG60_Disabled BPROT_CONFIG1_REGION60_Disabled
#define MPU_PROTENSET1_PROTREG60_Enabled BPROT_CONFIG1_REGION60_Enabled
#define MPU_PROTENSET1_PROTREG60_Set BPROT_CONFIG1_REGION60_Enabled
#define MPU_PROTENSET1_PROTREG59_Pos BPROT_CONFIG1_REGION59_Pos
#define MPU_PROTENSET1_PROTREG59_Msk BPROT_CONFIG1_REGION59_Msk
#define MPU_PROTENSET1_PROTREG59_Disabled BPROT_CONFIG1_REGION59_Disabled
#define MPU_PROTENSET1_PROTREG59_Enabled BPROT_CONFIG1_REGION59_Enabled
#define MPU_PROTENSET1_PROTREG59_Set BPROT_CONFIG1_REGION59_Enabled
#define MPU_PROTENSET1_PROTREG58_Pos BPROT_CONFIG1_REGION58_Pos
#define MPU_PROTENSET1_PROTREG58_Msk BPROT_CONFIG1_REGION58_Msk
#define MPU_PROTENSET1_PROTREG58_Disabled BPROT_CONFIG1_REGION58_Disabled
#define MPU_PROTENSET1_PROTREG58_Enabled BPROT_CONFIG1_REGION58_Enabled
#define MPU_PROTENSET1_PROTREG58_Set BPROT_CONFIG1_REGION58_Enabled
#define MPU_PROTENSET1_PROTREG57_Pos BPROT_CONFIG1_REGION57_Pos
#define MPU_PROTENSET1_PROTREG57_Msk BPROT_CONFIG1_REGION57_Msk
#define MPU_PROTENSET1_PROTREG57_Disabled BPROT_CONFIG1_REGION57_Disabled
#define MPU_PROTENSET1_PROTREG57_Enabled BPROT_CONFIG1_REGION57_Enabled
#define MPU_PROTENSET1_PROTREG57_Set BPROT_CONFIG1_REGION57_Enabled
#define MPU_PROTENSET1_PROTREG56_Pos BPROT_CONFIG1_REGION56_Pos
#define MPU_PROTENSET1_PROTREG56_Msk BPROT_CONFIG1_REGION56_Msk
#define MPU_PROTENSET1_PROTREG56_Disabled BPROT_CONFIG1_REGION56_Disabled
#define MPU_PROTENSET1_PROTREG56_Enabled BPROT_CONFIG1_REGION56_Enabled
#define MPU_PROTENSET1_PROTREG56_Set BPROT_CONFIG1_REGION56_Enabled
#define MPU_PROTENSET1_PROTREG55_Pos BPROT_CONFIG1_REGION55_Pos
#define MPU_PROTENSET1_PROTREG55_Msk BPROT_CONFIG1_REGION55_Msk
#define MPU_PROTENSET1_PROTREG55_Disabled BPROT_CONFIG1_REGION55_Disabled
#define MPU_PROTENSET1_PROTREG55_Enabled BPROT_CONFIG1_REGION55_Enabled
#define MPU_PROTENSET1_PROTREG55_Set BPROT_CONFIG1_REGION55_Enabled
#define MPU_PROTENSET1_PROTREG54_Pos BPROT_CONFIG1_REGION54_Pos
#define MPU_PROTENSET1_PROTREG54_Msk BPROT_CONFIG1_REGION54_Msk
#define MPU_PROTENSET1_PROTREG54_Disabled BPROT_CONFIG1_REGION54_Disabled
#define MPU_PROTENSET1_PROTREG54_Enabled BPROT_CONFIG1_REGION54_Enabled
#define MPU_PROTENSET1_PROTREG54_Set BPROT_CONFIG1_REGION54_Enabled
#define MPU_PROTENSET1_PROTREG53_Pos BPROT_CONFIG1_REGION53_Pos
#define MPU_PROTENSET1_PROTREG53_Msk BPROT_CONFIG1_REGION53_Msk
#define MPU_PROTENSET1_PROTREG53_Disabled BPROT_CONFIG1_REGION53_Disabled
#define MPU_PROTENSET1_PROTREG53_Enabled BPROT_CONFIG1_REGION53_Enabled
#define MPU_PROTENSET1_PROTREG53_Set BPROT_CONFIG1_REGION53_Enabled
#define MPU_PROTENSET1_PROTREG52_Pos BPROT_CONFIG1_REGION52_Pos
#define MPU_PROTENSET1_PROTREG52_Msk BPROT_CONFIG1_REGION52_Msk
#define MPU_PROTENSET1_PROTREG52_Disabled BPROT_CONFIG1_REGION52_Disabled
#define MPU_PROTENSET1_PROTREG52_Enabled BPROT_CONFIG1_REGION52_Enabled
#define MPU_PROTENSET1_PROTREG52_Set BPROT_CONFIG1_REGION52_Enabled
#define MPU_PROTENSET1_PROTREG51_Pos BPROT_CONFIG1_REGION51_Pos
#define MPU_PROTENSET1_PROTREG51_Msk BPROT_CONFIG1_REGION51_Msk
#define MPU_PROTENSET1_PROTREG51_Disabled BPROT_CONFIG1_REGION51_Disabled
#define MPU_PROTENSET1_PROTREG51_Enabled BPROT_CONFIG1_REGION51_Enabled
#define MPU_PROTENSET1_PROTREG51_Set BPROT_CONFIG1_REGION51_Enabled
#define MPU_PROTENSET1_PROTREG50_Pos BPROT_CONFIG1_REGION50_Pos
#define MPU_PROTENSET1_PROTREG50_Msk BPROT_CONFIG1_REGION50_Msk
#define MPU_PROTENSET1_PROTREG50_Disabled BPROT_CONFIG1_REGION50_Disabled
#define MPU_PROTENSET1_PROTREG50_Enabled BPROT_CONFIG1_REGION50_Enabled
#define MPU_PROTENSET1_PROTREG50_Set BPROT_CONFIG1_REGION50_Enabled
#define MPU_PROTENSET1_PROTREG49_Pos BPROT_CONFIG1_REGION49_Pos
#define MPU_PROTENSET1_PROTREG49_Msk BPROT_CONFIG1_REGION49_Msk
#define MPU_PROTENSET1_PROTREG49_Disabled BPROT_CONFIG1_REGION49_Disabled
#define MPU_PROTENSET1_PROTREG49_Enabled BPROT_CONFIG1_REGION49_Enabled
#define MPU_PROTENSET1_PROTREG49_Set BPROT_CONFIG1_REGION49_Enabled
#define MPU_PROTENSET1_PROTREG48_Pos BPROT_CONFIG1_REGION48_Pos
#define MPU_PROTENSET1_PROTREG48_Msk BPROT_CONFIG1_REGION48_Msk
#define MPU_PROTENSET1_PROTREG48_Disabled BPROT_CONFIG1_REGION48_Disabled
#define MPU_PROTENSET1_PROTREG48_Enabled BPROT_CONFIG1_REGION48_Enabled
#define MPU_PROTENSET1_PROTREG48_Set BPROT_CONFIG1_REGION48_Enabled
#define MPU_PROTENSET1_PROTREG47_Pos BPROT_CONFIG1_REGION47_Pos
#define MPU_PROTENSET1_PROTREG47_Msk BPROT_CONFIG1_REGION47_Msk
#define MPU_PROTENSET1_PROTREG47_Disabled BPROT_CONFIG1_REGION47_Disabled
#define MPU_PROTENSET1_PROTREG47_Enabled BPROT_CONFIG1_REGION47_Enabled
#define MPU_PROTENSET1_PROTREG47_Set BPROT_CONFIG1_REGION47_Enabled
#define MPU_PROTENSET1_PROTREG46_Pos BPROT_CONFIG1_REGION46_Pos
#define MPU_PROTENSET1_PROTREG46_Msk BPROT_CONFIG1_REGION46_Msk
#define MPU_PROTENSET1_PROTREG46_Disabled BPROT_CONFIG1_REGION46_Disabled
#define MPU_PROTENSET1_PROTREG46_Enabled BPROT_CONFIG1_REGION46_Enabled
#define MPU_PROTENSET1_PROTREG46_Set BPROT_CONFIG1_REGION46_Enabled
#define MPU_PROTENSET1_PROTREG45_Pos BPROT_CONFIG1_REGION45_Pos
#define MPU_PROTENSET1_PROTREG45_Msk BPROT_CONFIG1_REGION45_Msk
#define MPU_PROTENSET1_PROTREG45_Disabled BPROT_CONFIG1_REGION45_Disabled
#define MPU_PROTENSET1_PROTREG45_Enabled BPROT_CONFIG1_REGION45_Enabled
#define MPU_PROTENSET1_PROTREG45_Set BPROT_CONFIG1_REGION45_Enabled
#define MPU_PROTENSET1_PROTREG44_Pos BPROT_CONFIG1_REGION44_Pos
#define MPU_PROTENSET1_PROTREG44_Msk BPROT_CONFIG1_REGION44_Msk
#define MPU_PROTENSET1_PROTREG44_Disabled BPROT_CONFIG1_REGION44_Disabled
#define MPU_PROTENSET1_PROTREG44_Enabled BPROT_CONFIG1_REGION44_Enabled
#define MPU_PROTENSET1_PROTREG44_Set BPROT_CONFIG1_REGION44_Enabled
#define MPU_PROTENSET1_PROTREG43_Pos BPROT_CONFIG1_REGION43_Pos
#define MPU_PROTENSET1_PROTREG43_Msk BPROT_CONFIG1_REGION43_Msk
#define MPU_PROTENSET1_PROTREG43_Disabled BPROT_CONFIG1_REGION43_Disabled
#define MPU_PROTENSET1_PROTREG43_Enabled BPROT_CONFIG1_REGION43_Enabled
#define MPU_PROTENSET1_PROTREG43_Set BPROT_CONFIG1_REGION43_Enabled
#define MPU_PROTENSET1_PROTREG42_Pos BPROT_CONFIG1_REGION42_Pos
#define MPU_PROTENSET1_PROTREG42_Msk BPROT_CONFIG1_REGION42_Msk
#define MPU_PROTENSET1_PROTREG42_Disabled BPROT_CONFIG1_REGION42_Disabled
#define MPU_PROTENSET1_PROTREG42_Enabled BPROT_CONFIG1_REGION42_Enabled
#define MPU_PROTENSET1_PROTREG42_Set BPROT_CONFIG1_REGION42_Enabled
#define MPU_PROTENSET1_PROTREG41_Pos BPROT_CONFIG1_REGION41_Pos
#define MPU_PROTENSET1_PROTREG41_Msk BPROT_CONFIG1_REGION41_Msk
#define MPU_PROTENSET1_PROTREG41_Disabled BPROT_CONFIG1_REGION41_Disabled
#define MPU_PROTENSET1_PROTREG41_Enabled BPROT_CONFIG1_REGION41_Enabled
#define MPU_PROTENSET1_PROTREG41_Set BPROT_CONFIG1_REGION41_Enabled
#define MPU_PROTENSET1_PROTREG40_Pos BPROT_CONFIG1_REGION40_Pos
#define MPU_PROTENSET1_PROTREG40_Msk BPROT_CONFIG1_REGION40_Msk
#define MPU_PROTENSET1_PROTREG40_Disabled BPROT_CONFIG1_REGION40_Disabled
#define MPU_PROTENSET1_PROTREG40_Enabled BPROT_CONFIG1_REGION40_Enabled
#define MPU_PROTENSET1_PROTREG40_Set BPROT_CONFIG1_REGION40_Enabled
#define MPU_PROTENSET1_PROTREG39_Pos BPROT_CONFIG1_REGION39_Pos
#define MPU_PROTENSET1_PROTREG39_Msk BPROT_CONFIG1_REGION39_Msk
#define MPU_PROTENSET1_PROTREG39_Disabled BPROT_CONFIG1_REGION39_Disabled
#define MPU_PROTENSET1_PROTREG39_Enabled BPROT_CONFIG1_REGION39_Enabled
#define MPU_PROTENSET1_PROTREG39_Set BPROT_CONFIG1_REGION39_Enabled
#define MPU_PROTENSET1_PROTREG38_Pos BPROT_CONFIG1_REGION38_Pos
#define MPU_PROTENSET1_PROTREG38_Msk BPROT_CONFIG1_REGION38_Msk
#define MPU_PROTENSET1_PROTREG38_Disabled BPROT_CONFIG1_REGION38_Disabled
#define MPU_PROTENSET1_PROTREG38_Enabled BPROT_CONFIG1_REGION38_Enabled
#define MPU_PROTENSET1_PROTREG38_Set BPROT_CONFIG1_REGION38_Enabled
#define MPU_PROTENSET1_PROTREG37_Pos BPROT_CONFIG1_REGION37_Pos
#define MPU_PROTENSET1_PROTREG37_Msk BPROT_CONFIG1_REGION37_Msk
#define MPU_PROTENSET1_PROTREG37_Disabled BPROT_CONFIG1_REGION37_Disabled
#define MPU_PROTENSET1_PROTREG37_Enabled BPROT_CONFIG1_REGION37_Enabled
#define MPU_PROTENSET1_PROTREG37_Set BPROT_CONFIG1_REGION37_Enabled
#define MPU_PROTENSET1_PROTREG36_Pos BPROT_CONFIG1_REGION36_Pos
#define MPU_PROTENSET1_PROTREG36_Msk BPROT_CONFIG1_REGION36_Msk
#define MPU_PROTENSET1_PROTREG36_Disabled BPROT_CONFIG1_REGION36_Disabled
#define MPU_PROTENSET1_PROTREG36_Enabled BPROT_CONFIG1_REGION36_Enabled
#define MPU_PROTENSET1_PROTREG36_Set BPROT_CONFIG1_REGION36_Enabled
#define MPU_PROTENSET1_PROTREG35_Pos BPROT_CONFIG1_REGION35_Pos
#define MPU_PROTENSET1_PROTREG35_Msk BPROT_CONFIG1_REGION35_Msk
#define MPU_PROTENSET1_PROTREG35_Disabled BPROT_CONFIG1_REGION35_Disabled
#define MPU_PROTENSET1_PROTREG35_Enabled BPROT_CONFIG1_REGION35_Enabled
#define MPU_PROTENSET1_PROTREG35_Set BPROT_CONFIG1_REGION35_Enabled
#define MPU_PROTENSET1_PROTREG34_Pos BPROT_CONFIG1_REGION34_Pos
#define MPU_PROTENSET1_PROTREG34_Msk BPROT_CONFIG1_REGION34_Msk
#define MPU_PROTENSET1_PROTREG34_Disabled BPROT_CONFIG1_REGION34_Disabled
#define MPU_PROTENSET1_PROTREG34_Enabled BPROT_CONFIG1_REGION34_Enabled
#define MPU_PROTENSET1_PROTREG34_Set BPROT_CONFIG1_REGION34_Enabled
#define MPU_PROTENSET1_PROTREG33_Pos BPROT_CONFIG1_REGION33_Pos
#define MPU_PROTENSET1_PROTREG33_Msk BPROT_CONFIG1_REGION33_Msk
#define MPU_PROTENSET1_PROTREG33_Disabled BPROT_CONFIG1_REGION33_Disabled
#define MPU_PROTENSET1_PROTREG33_Enabled BPROT_CONFIG1_REGION33_Enabled
#define MPU_PROTENSET1_PROTREG33_Set BPROT_CONFIG1_REGION33_Enabled
#define MPU_PROTENSET1_PROTREG32_Pos BPROT_CONFIG1_REGION32_Pos
#define MPU_PROTENSET1_PROTREG32_Msk BPROT_CONFIG1_REGION32_Msk
#define MPU_PROTENSET1_PROTREG32_Disabled BPROT_CONFIG1_REGION32_Disabled
#define MPU_PROTENSET1_PROTREG32_Enabled BPROT_CONFIG1_REGION32_Enabled
#define MPU_PROTENSET1_PROTREG32_Set BPROT_CONFIG1_REGION32_Enabled
#define MPU_PROTENSET0_PROTREG31_Pos BPROT_CONFIG0_REGION31_Pos
#define MPU_PROTENSET0_PROTREG31_Msk BPROT_CONFIG0_REGION31_Msk
#define MPU_PROTENSET0_PROTREG31_Disabled BPROT_CONFIG0_REGION31_Disabled
#define MPU_PROTENSET0_PROTREG31_Enabled BPROT_CONFIG0_REGION31_Enabled
#define MPU_PROTENSET0_PROTREG31_Set BPROT_CONFIG0_REGION31_Enabled
#define MPU_PROTENSET0_PROTREG30_Pos BPROT_CONFIG0_REGION30_Pos
#define MPU_PROTENSET0_PROTREG30_Msk BPROT_CONFIG0_REGION30_Msk
#define MPU_PROTENSET0_PROTREG30_Disabled BPROT_CONFIG0_REGION30_Disabled
#define MPU_PROTENSET0_PROTREG30_Enabled BPROT_CONFIG0_REGION30_Enabled
#define MPU_PROTENSET0_PROTREG30_Set BPROT_CONFIG0_REGION30_Enabled
#define MPU_PROTENSET0_PROTREG29_Pos BPROT_CONFIG0_REGION29_Pos
#define MPU_PROTENSET0_PROTREG29_Msk BPROT_CONFIG0_REGION29_Msk
#define MPU_PROTENSET0_PROTREG29_Disabled BPROT_CONFIG0_REGION29_Disabled
#define MPU_PROTENSET0_PROTREG29_Enabled BPROT_CONFIG0_REGION29_Enabled
#define MPU_PROTENSET0_PROTREG29_Set BPROT_CONFIG0_REGION29_Enabled
#define MPU_PROTENSET0_PROTREG28_Pos BPROT_CONFIG0_REGION28_Pos
#define MPU_PROTENSET0_PROTREG28_Msk BPROT_CONFIG0_REGION28_Msk
#define MPU_PROTENSET0_PROTREG28_Disabled BPROT_CONFIG0_REGION28_Disabled
#define MPU_PROTENSET0_PROTREG28_Enabled BPROT_CONFIG0_REGION28_Enabled
#define MPU_PROTENSET0_PROTREG28_Set BPROT_CONFIG0_REGION28_Enabled
#define MPU_PROTENSET0_PROTREG27_Pos BPROT_CONFIG0_REGION27_Pos
#define MPU_PROTENSET0_PROTREG27_Msk BPROT_CONFIG0_REGION27_Msk
#define MPU_PROTENSET0_PROTREG27_Disabled BPROT_CONFIG0_REGION27_Disabled
#define MPU_PROTENSET0_PROTREG27_Enabled BPROT_CONFIG0_REGION27_Enabled
#define MPU_PROTENSET0_PROTREG27_Set BPROT_CONFIG0_REGION27_Enabled
#define MPU_PROTENSET0_PROTREG26_Pos BPROT_CONFIG0_REGION26_Pos
#define MPU_PROTENSET0_PROTREG26_Msk BPROT_CONFIG0_REGION26_Msk
#define MPU_PROTENSET0_PROTREG26_Disabled BPROT_CONFIG0_REGION26_Disabled
#define MPU_PROTENSET0_PROTREG26_Enabled BPROT_CONFIG0_REGION26_Enabled
#define MPU_PROTENSET0_PROTREG26_Set BPROT_CONFIG0_REGION26_Enabled
#define MPU_PROTENSET0_PROTREG25_Pos BPROT_CONFIG0_REGION25_Pos
#define MPU_PROTENSET0_PROTREG25_Msk BPROT_CONFIG0_REGION25_Msk
#define MPU_PROTENSET0_PROTREG25_Disabled BPROT_CONFIG0_REGION25_Disabled
#define MPU_PROTENSET0_PROTREG25_Enabled BPROT_CONFIG0_REGION25_Enabled
#define MPU_PROTENSET0_PROTREG25_Set BPROT_CONFIG0_REGION25_Enabled
#define MPU_PROTENSET0_PROTREG24_Pos BPROT_CONFIG0_REGION24_Pos
#define MPU_PROTENSET0_PROTREG24_Msk BPROT_CONFIG0_REGION24_Msk
#define MPU_PROTENSET0_PROTREG24_Disabled BPROT_CONFIG0_REGION24_Disabled
#define MPU_PROTENSET0_PROTREG24_Enabled BPROT_CONFIG0_REGION24_Enabled
#define MPU_PROTENSET0_PROTREG24_Set BPROT_CONFIG0_REGION24_Enabled
#define MPU_PROTENSET0_PROTREG23_Pos BPROT_CONFIG0_REGION23_Pos
#define MPU_PROTENSET0_PROTREG23_Msk BPROT_CONFIG0_REGION23_Msk
#define MPU_PROTENSET0_PROTREG23_Disabled BPROT_CONFIG0_REGION23_Disabled
#define MPU_PROTENSET0_PROTREG23_Enabled BPROT_CONFIG0_REGION23_Enabled
#define MPU_PROTENSET0_PROTREG23_Set BPROT_CONFIG0_REGION23_Enabled
#define MPU_PROTENSET0_PROTREG22_Pos BPROT_CONFIG0_REGION22_Pos
#define MPU_PROTENSET0_PROTREG22_Msk BPROT_CONFIG0_REGION22_Msk
#define MPU_PROTENSET0_PROTREG22_Disabled BPROT_CONFIG0_REGION22_Disabled
#define MPU_PROTENSET0_PROTREG22_Enabled BPROT_CONFIG0_REGION22_Enabled
#define MPU_PROTENSET0_PROTREG22_Set BPROT_CONFIG0_REGION22_Enabled
#define MPU_PROTENSET0_PROTREG21_Pos BPROT_CONFIG0_REGION21_Pos
#define MPU_PROTENSET0_PROTREG21_Msk BPROT_CONFIG0_REGION21_Msk
#define MPU_PROTENSET0_PROTREG21_Disabled BPROT_CONFIG0_REGION21_Disabled
#define MPU_PROTENSET0_PROTREG21_Enabled BPROT_CONFIG0_REGION21_Enabled
#define MPU_PROTENSET0_PROTREG21_Set BPROT_CONFIG0_REGION21_Enabled
#define MPU_PROTENSET0_PROTREG20_Pos BPROT_CONFIG0_REGION20_Pos
#define MPU_PROTENSET0_PROTREG20_Msk BPROT_CONFIG0_REGION20_Msk
#define MPU_PROTENSET0_PROTREG20_Disabled BPROT_CONFIG0_REGION20_Disabled
#define MPU_PROTENSET0_PROTREG20_Enabled BPROT_CONFIG0_REGION20_Enabled
#define MPU_PROTENSET0_PROTREG20_Set BPROT_CONFIG0_REGION20_Enabled
#define MPU_PROTENSET0_PROTREG19_Pos BPROT_CONFIG0_REGION19_Pos
#define MPU_PROTENSET0_PROTREG19_Msk BPROT_CONFIG0_REGION19_Msk
#define MPU_PROTENSET0_PROTREG19_Disabled BPROT_CONFIG0_REGION19_Disabled
#define MPU_PROTENSET0_PROTREG19_Enabled BPROT_CONFIG0_REGION19_Enabled
#define MPU_PROTENSET0_PROTREG19_Set BPROT_CONFIG0_REGION19_Enabled
#define MPU_PROTENSET0_PROTREG18_Pos BPROT_CONFIG0_REGION18_Pos
#define MPU_PROTENSET0_PROTREG18_Msk BPROT_CONFIG0_REGION18_Msk
#define MPU_PROTENSET0_PROTREG18_Disabled BPROT_CONFIG0_REGION18_Disabled
#define MPU_PROTENSET0_PROTREG18_Enabled BPROT_CONFIG0_REGION18_Enabled
#define MPU_PROTENSET0_PROTREG18_Set BPROT_CONFIG0_REGION18_Enabled
#define MPU_PROTENSET0_PROTREG17_Pos BPROT_CONFIG0_REGION17_Pos
#define MPU_PROTENSET0_PROTREG17_Msk BPROT_CONFIG0_REGION17_Msk
#define MPU_PROTENSET0_PROTREG17_Disabled BPROT_CONFIG0_REGION17_Disabled
#define MPU_PROTENSET0_PROTREG17_Enabled BPROT_CONFIG0_REGION17_Enabled
#define MPU_PROTENSET0_PROTREG17_Set BPROT_CONFIG0_REGION17_Enabled
#define MPU_PROTENSET0_PROTREG16_Pos BPROT_CONFIG0_REGION16_Pos
#define MPU_PROTENSET0_PROTREG16_Msk BPROT_CONFIG0_REGION16_Msk
#define MPU_PROTENSET0_PROTREG16_Disabled BPROT_CONFIG0_REGION16_Disabled
#define MPU_PROTENSET0_PROTREG16_Enabled BPROT_CONFIG0_REGION16_Enabled
#define MPU_PROTENSET0_PROTREG16_Set BPROT_CONFIG0_REGION16_Enabled
#define MPU_PROTENSET0_PROTREG15_Pos BPROT_CONFIG0_REGION15_Pos
#define MPU_PROTENSET0_PROTREG15_Msk BPROT_CONFIG0_REGION15_Msk
#define MPU_PROTENSET0_PROTREG15_Disabled BPROT_CONFIG0_REGION15_Disabled
#define MPU_PROTENSET0_PROTREG15_Enabled BPROT_CONFIG0_REGION15_Enabled
#define MPU_PROTENSET0_PROTREG15_Set BPROT_CONFIG0_REGION15_Enabled
#define MPU_PROTENSET0_PROTREG14_Pos BPROT_CONFIG0_REGION14_Pos
#define MPU_PROTENSET0_PROTREG14_Msk BPROT_CONFIG0_REGION14_Msk
#define MPU_PROTENSET0_PROTREG14_Disabled BPROT_CONFIG0_REGION14_Disabled
#define MPU_PROTENSET0_PROTREG14_Enabled BPROT_CONFIG0_REGION14_Enabled
#define MPU_PROTENSET0_PROTREG14_Set BPROT_CONFIG0_REGION14_Enabled
#define MPU_PROTENSET0_PROTREG13_Pos BPROT_CONFIG0_REGION13_Pos
#define MPU_PROTENSET0_PROTREG13_Msk BPROT_CONFIG0_REGION13_Msk
#define MPU_PROTENSET0_PROTREG13_Disabled BPROT_CONFIG0_REGION13_Disabled
#define MPU_PROTENSET0_PROTREG13_Enabled BPROT_CONFIG0_REGION13_Enabled
#define MPU_PROTENSET0_PROTREG13_Set BPROT_CONFIG0_REGION13_Enabled
#define MPU_PROTENSET0_PROTREG12_Pos BPROT_CONFIG0_REGION12_Pos
#define MPU_PROTENSET0_PROTREG12_Msk BPROT_CONFIG0_REGION12_Msk
#define MPU_PROTENSET0_PROTREG12_Disabled BPROT_CONFIG0_REGION12_Disabled
#define MPU_PROTENSET0_PROTREG12_Enabled BPROT_CONFIG0_REGION12_Enabled
#define MPU_PROTENSET0_PROTREG12_Set BPROT_CONFIG0_REGION12_Enabled
#define MPU_PROTENSET0_PROTREG11_Pos BPROT_CONFIG0_REGION11_Pos
#define MPU_PROTENSET0_PROTREG11_Msk BPROT_CONFIG0_REGION11_Msk
#define MPU_PROTENSET0_PROTREG11_Disabled BPROT_CONFIG0_REGION11_Disabled
#define MPU_PROTENSET0_PROTREG11_Enabled BPROT_CONFIG0_REGION11_Enabled
#define MPU_PROTENSET0_PROTREG11_Set BPROT_CONFIG0_REGION11_Enabled
#define MPU_PROTENSET0_PROTREG10_Pos BPROT_CONFIG0_REGION10_Pos
#define MPU_PROTENSET0_PROTREG10_Msk BPROT_CONFIG0_REGION10_Msk
#define MPU_PROTENSET0_PROTREG10_Disabled BPROT_CONFIG0_REGION10_Disabled
#define MPU_PROTENSET0_PROTREG10_Enabled BPROT_CONFIG0_REGION10_Enabled
#define MPU_PROTENSET0_PROTREG10_Set BPROT_CONFIG0_REGION10_Enabled
#define MPU_PROTENSET0_PROTREG9_Pos BPROT_CONFIG0_REGION9_Pos
#define MPU_PROTENSET0_PROTREG9_Msk BPROT_CONFIG0_REGION9_Msk
#define MPU_PROTENSET0_PROTREG9_Disabled BPROT_CONFIG0_REGION9_Disabled
#define MPU_PROTENSET0_PROTREG9_Enabled BPROT_CONFIG0_REGION9_Enabled
#define MPU_PROTENSET0_PROTREG9_Set BPROT_CONFIG0_REGION9_Enabled
#define MPU_PROTENSET0_PROTREG8_Pos BPROT_CONFIG0_REGION8_Pos
#define MPU_PROTENSET0_PROTREG8_Msk BPROT_CONFIG0_REGION8_Msk
#define MPU_PROTENSET0_PROTREG8_Disabled BPROT_CONFIG0_REGION8_Disabled
#define MPU_PROTENSET0_PROTREG8_Enabled BPROT_CONFIG0_REGION8_Enabled
#define MPU_PROTENSET0_PROTREG8_Set BPROT_CONFIG0_REGION8_Enabled
#define MPU_PROTENSET0_PROTREG7_Pos BPROT_CONFIG0_REGION7_Pos
#define MPU_PROTENSET0_PROTREG7_Msk BPROT_CONFIG0_REGION7_Msk
#define MPU_PROTENSET0_PROTREG7_Disabled BPROT_CONFIG0_REGION7_Disabled
#define MPU_PROTENSET0_PROTREG7_Enabled BPROT_CONFIG0_REGION7_Enabled
#define MPU_PROTENSET0_PROTREG7_Set BPROT_CONFIG0_REGION7_Enabled
#define MPU_PROTENSET0_PROTREG6_Pos BPROT_CONFIG0_REGION6_Pos
#define MPU_PROTENSET0_PROTREG6_Msk BPROT_CONFIG0_REGION6_Msk
#define MPU_PROTENSET0_PROTREG6_Disabled BPROT_CONFIG0_REGION6_Disabled
#define MPU_PROTENSET0_PROTREG6_Enabled BPROT_CONFIG0_REGION6_Enabled
#define MPU_PROTENSET0_PROTREG6_Set BPROT_CONFIG0_REGION6_Enabled
#define MPU_PROTENSET0_PROTREG5_Pos BPROT_CONFIG0_REGION5_Pos
#define MPU_PROTENSET0_PROTREG5_Msk BPROT_CONFIG0_REGION5_Msk
#define MPU_PROTENSET0_PROTREG5_Disabled BPROT_CONFIG0_REGION5_Disabled
#define MPU_PROTENSET0_PROTREG5_Enabled BPROT_CONFIG0_REGION5_Enabled
#define MPU_PROTENSET0_PROTREG5_Set BPROT_CONFIG0_REGION5_Enabled
#define MPU_PROTENSET0_PROTREG4_Pos BPROT_CONFIG0_REGION4_Pos
#define MPU_PROTENSET0_PROTREG4_Msk BPROT_CONFIG0_REGION4_Msk
#define MPU_PROTENSET0_PROTREG4_Disabled BPROT_CONFIG0_REGION4_Disabled
#define MPU_PROTENSET0_PROTREG4_Enabled BPROT_CONFIG0_REGION4_Enabled
#define MPU_PROTENSET0_PROTREG4_Set BPROT_CONFIG0_REGION4_Enabled
#define MPU_PROTENSET0_PROTREG3_Pos BPROT_CONFIG0_REGION3_Pos
#define MPU_PROTENSET0_PROTREG3_Msk BPROT_CONFIG0_REGION3_Msk
#define MPU_PROTENSET0_PROTREG3_Disabled BPROT_CONFIG0_REGION3_Disabled
#define MPU_PROTENSET0_PROTREG3_Enabled BPROT_CONFIG0_REGION3_Enabled
#define MPU_PROTENSET0_PROTREG3_Set BPROT_CONFIG0_REGION3_Enabled
#define MPU_PROTENSET0_PROTREG2_Pos BPROT_CONFIG0_REGION2_Pos
#define MPU_PROTENSET0_PROTREG2_Msk BPROT_CONFIG0_REGION2_Msk
#define MPU_PROTENSET0_PROTREG2_Disabled BPROT_CONFIG0_REGION2_Disabled
#define MPU_PROTENSET0_PROTREG2_Enabled BPROT_CONFIG0_REGION2_Enabled
#define MPU_PROTENSET0_PROTREG2_Set BPROT_CONFIG0_REGION2_Enabled
#define MPU_PROTENSET0_PROTREG1_Pos BPROT_CONFIG0_REGION1_Pos
#define MPU_PROTENSET0_PROTREG1_Msk BPROT_CONFIG0_REGION1_Msk
#define MPU_PROTENSET0_PROTREG1_Disabled BPROT_CONFIG0_REGION1_Disabled
#define MPU_PROTENSET0_PROTREG1_Enabled BPROT_CONFIG0_REGION1_Enabled
#define MPU_PROTENSET0_PROTREG1_Set BPROT_CONFIG0_REGION1_Enabled
#define MPU_PROTENSET0_PROTREG0_Pos BPROT_CONFIG0_REGION0_Pos
#define MPU_PROTENSET0_PROTREG0_Msk BPROT_CONFIG0_REGION0_Msk
#define MPU_PROTENSET0_PROTREG0_Disabled BPROT_CONFIG0_REGION0_Disabled
#define MPU_PROTENSET0_PROTREG0_Enabled BPROT_CONFIG0_REGION0_Enabled
#define MPU_PROTENSET0_PROTREG0_Set BPROT_CONFIG0_REGION0_Enabled
/* From nrf51_deprecated.h */
/* NVMC */
/* The register ERASEPROTECTEDPAGE changed name to ERASEPCR0 in the documentation. */
#define ERASEPROTECTEDPAGE ERASEPCR0
/* IRQ */
/* COMP module was eliminated. Adapted to nrf52 headers. */
#define LPCOMP_COMP_IRQHandler COMP_LPCOMP_IRQHandler
#define LPCOMP_COMP_IRQn COMP_LPCOMP_IRQn
/* RADIO */
/* The name of the field SKIPADDR was corrected. Old macros added for compatibility. */
#define RADIO_CRCCNF_SKIP_ADDR_Pos RADIO_CRCCNF_SKIPADDR_Pos
#define RADIO_CRCCNF_SKIP_ADDR_Msk RADIO_CRCCNF_SKIPADDR_Msk
#define RADIO_CRCCNF_SKIP_ADDR_Include RADIO_CRCCNF_SKIPADDR_Include
#define RADIO_CRCCNF_SKIP_ADDR_Skip RADIO_CRCCNF_SKIPADDR_Skip
/* FICR */
/* The registers FICR.DEVICEID0 and FICR.DEVICEID1 were renamed into an array. */
#define DEVICEID0 DEVICEID[0]
#define DEVICEID1 DEVICEID[1]
/* The registers FICR.ER0, FICR.ER1, FICR.ER2 and FICR.ER3 were renamed into an array. */
#define ER0 ER[0]
#define ER1 ER[1]
#define ER2 ER[2]
#define ER3 ER[3]
/* The registers FICR.IR0, FICR.IR1, FICR.IR2 and FICR.IR3 were renamed into an array. */
#define IR0 IR[0]
#define IR1 IR[1]
#define IR2 IR[2]
#define IR3 IR[3]
/* The registers FICR.DEVICEADDR0 and FICR.DEVICEADDR1 were renamed into an array. */
#define DEVICEADDR0 DEVICEADDR[0]
#define DEVICEADDR1 DEVICEADDR[1]
/* PPI */
/* The tasks PPI.TASKS_CHGxEN and PPI.TASKS_CHGxDIS were renamed into an array of structs. */
#define TASKS_CHG0EN TASKS_CHG[0].EN
#define TASKS_CHG0DIS TASKS_CHG[0].DIS
#define TASKS_CHG1EN TASKS_CHG[1].EN
#define TASKS_CHG1DIS TASKS_CHG[1].DIS
#define TASKS_CHG2EN TASKS_CHG[2].EN
#define TASKS_CHG2DIS TASKS_CHG[2].DIS
#define TASKS_CHG3EN TASKS_CHG[3].EN
#define TASKS_CHG3DIS TASKS_CHG[3].DIS
/* The registers PPI.CHx_EEP and PPI.CHx_TEP were renamed into an array of structs. */
#define CH0_EEP CH[0].EEP
#define CH0_TEP CH[0].TEP
#define CH1_EEP CH[1].EEP
#define CH1_TEP CH[1].TEP
#define CH2_EEP CH[2].EEP
#define CH2_TEP CH[2].TEP
#define CH3_EEP CH[3].EEP
#define CH3_TEP CH[3].TEP
#define CH4_EEP CH[4].EEP
#define CH4_TEP CH[4].TEP
#define CH5_EEP CH[5].EEP
#define CH5_TEP CH[5].TEP
#define CH6_EEP CH[6].EEP
#define CH6_TEP CH[6].TEP
#define CH7_EEP CH[7].EEP
#define CH7_TEP CH[7].TEP
#define CH8_EEP CH[8].EEP
#define CH8_TEP CH[8].TEP
#define CH9_EEP CH[9].EEP
#define CH9_TEP CH[9].TEP
#define CH10_EEP CH[10].EEP
#define CH10_TEP CH[10].TEP
#define CH11_EEP CH[11].EEP
#define CH11_TEP CH[11].TEP
#define CH12_EEP CH[12].EEP
#define CH12_TEP CH[12].TEP
#define CH13_EEP CH[13].EEP
#define CH13_TEP CH[13].TEP
#define CH14_EEP CH[14].EEP
#define CH14_TEP CH[14].TEP
#define CH15_EEP CH[15].EEP
#define CH15_TEP CH[15].TEP
/* The registers PPI.CHG0, PPI.CHG1, PPI.CHG2 and PPI.CHG3 were renamed into an array. */
#define CHG0 CHG[0]
#define CHG1 CHG[1]
#define CHG2 CHG[2]
#define CHG3 CHG[3]
/* All bitfield macros for the CHGx registers therefore changed name. */
#define PPI_CHG0_CH15_Pos PPI_CHG_CH15_Pos
#define PPI_CHG0_CH15_Msk PPI_CHG_CH15_Msk
#define PPI_CHG0_CH15_Excluded PPI_CHG_CH15_Excluded
#define PPI_CHG0_CH15_Included PPI_CHG_CH15_Included
#define PPI_CHG0_CH14_Pos PPI_CHG_CH14_Pos
#define PPI_CHG0_CH14_Msk PPI_CHG_CH14_Msk
#define PPI_CHG0_CH14_Excluded PPI_CHG_CH14_Excluded
#define PPI_CHG0_CH14_Included PPI_CHG_CH14_Included
#define PPI_CHG0_CH13_Pos PPI_CHG_CH13_Pos
#define PPI_CHG0_CH13_Msk PPI_CHG_CH13_Msk
#define PPI_CHG0_CH13_Excluded PPI_CHG_CH13_Excluded
#define PPI_CHG0_CH13_Included PPI_CHG_CH13_Included
#define PPI_CHG0_CH12_Pos PPI_CHG_CH12_Pos
#define PPI_CHG0_CH12_Msk PPI_CHG_CH12_Msk
#define PPI_CHG0_CH12_Excluded PPI_CHG_CH12_Excluded
#define PPI_CHG0_CH12_Included PPI_CHG_CH12_Included
#define PPI_CHG0_CH11_Pos PPI_CHG_CH11_Pos
#define PPI_CHG0_CH11_Msk PPI_CHG_CH11_Msk
#define PPI_CHG0_CH11_Excluded PPI_CHG_CH11_Excluded
#define PPI_CHG0_CH11_Included PPI_CHG_CH11_Included
#define PPI_CHG0_CH10_Pos PPI_CHG_CH10_Pos
#define PPI_CHG0_CH10_Msk PPI_CHG_CH10_Msk
#define PPI_CHG0_CH10_Excluded PPI_CHG_CH10_Excluded
#define PPI_CHG0_CH10_Included PPI_CHG_CH10_Included
#define PPI_CHG0_CH9_Pos PPI_CHG_CH9_Pos
#define PPI_CHG0_CH9_Msk PPI_CHG_CH9_Msk
#define PPI_CHG0_CH9_Excluded PPI_CHG_CH9_Excluded
#define PPI_CHG0_CH9_Included PPI_CHG_CH9_Included
#define PPI_CHG0_CH8_Pos PPI_CHG_CH8_Pos
#define PPI_CHG0_CH8_Msk PPI_CHG_CH8_Msk
#define PPI_CHG0_CH8_Excluded PPI_CHG_CH8_Excluded
#define PPI_CHG0_CH8_Included PPI_CHG_CH8_Included
#define PPI_CHG0_CH7_Pos PPI_CHG_CH7_Pos
#define PPI_CHG0_CH7_Msk PPI_CHG_CH7_Msk
#define PPI_CHG0_CH7_Excluded PPI_CHG_CH7_Excluded
#define PPI_CHG0_CH7_Included PPI_CHG_CH7_Included
#define PPI_CHG0_CH6_Pos PPI_CHG_CH6_Pos
#define PPI_CHG0_CH6_Msk PPI_CHG_CH6_Msk
#define PPI_CHG0_CH6_Excluded PPI_CHG_CH6_Excluded
#define PPI_CHG0_CH6_Included PPI_CHG_CH6_Included
#define PPI_CHG0_CH5_Pos PPI_CHG_CH5_Pos
#define PPI_CHG0_CH5_Msk PPI_CHG_CH5_Msk
#define PPI_CHG0_CH5_Excluded PPI_CHG_CH5_Excluded
#define PPI_CHG0_CH5_Included PPI_CHG_CH5_Included
#define PPI_CHG0_CH4_Pos PPI_CHG_CH4_Pos
#define PPI_CHG0_CH4_Msk PPI_CHG_CH4_Msk
#define PPI_CHG0_CH4_Excluded PPI_CHG_CH4_Excluded
#define PPI_CHG0_CH4_Included PPI_CHG_CH4_Included
#define PPI_CHG0_CH3_Pos PPI_CHG_CH3_Pos
#define PPI_CHG0_CH3_Msk PPI_CHG_CH3_Msk
#define PPI_CHG0_CH3_Excluded PPI_CHG_CH3_Excluded
#define PPI_CHG0_CH3_Included PPI_CHG_CH3_Included
#define PPI_CHG0_CH2_Pos PPI_CHG_CH2_Pos
#define PPI_CHG0_CH2_Msk PPI_CHG_CH2_Msk
#define PPI_CHG0_CH2_Excluded PPI_CHG_CH2_Excluded
#define PPI_CHG0_CH2_Included PPI_CHG_CH2_Included
#define PPI_CHG0_CH1_Pos PPI_CHG_CH1_Pos
#define PPI_CHG0_CH1_Msk PPI_CHG_CH1_Msk
#define PPI_CHG0_CH1_Excluded PPI_CHG_CH1_Excluded
#define PPI_CHG0_CH1_Included PPI_CHG_CH1_Included
#define PPI_CHG0_CH0_Pos PPI_CHG_CH0_Pos
#define PPI_CHG0_CH0_Msk PPI_CHG_CH0_Msk
#define PPI_CHG0_CH0_Excluded PPI_CHG_CH0_Excluded
#define PPI_CHG0_CH0_Included PPI_CHG_CH0_Included
#define PPI_CHG1_CH15_Pos PPI_CHG_CH15_Pos
#define PPI_CHG1_CH15_Msk PPI_CHG_CH15_Msk
#define PPI_CHG1_CH15_Excluded PPI_CHG_CH15_Excluded
#define PPI_CHG1_CH15_Included PPI_CHG_CH15_Included
#define PPI_CHG1_CH14_Pos PPI_CHG_CH14_Pos
#define PPI_CHG1_CH14_Msk PPI_CHG_CH14_Msk
#define PPI_CHG1_CH14_Excluded PPI_CHG_CH14_Excluded
#define PPI_CHG1_CH14_Included PPI_CHG_CH14_Included
#define PPI_CHG1_CH13_Pos PPI_CHG_CH13_Pos
#define PPI_CHG1_CH13_Msk PPI_CHG_CH13_Msk
#define PPI_CHG1_CH13_Excluded PPI_CHG_CH13_Excluded
#define PPI_CHG1_CH13_Included PPI_CHG_CH13_Included
#define PPI_CHG1_CH12_Pos PPI_CHG_CH12_Pos
#define PPI_CHG1_CH12_Msk PPI_CHG_CH12_Msk
#define PPI_CHG1_CH12_Excluded PPI_CHG_CH12_Excluded
#define PPI_CHG1_CH12_Included PPI_CHG_CH12_Included
#define PPI_CHG1_CH11_Pos PPI_CHG_CH11_Pos
#define PPI_CHG1_CH11_Msk PPI_CHG_CH11_Msk
#define PPI_CHG1_CH11_Excluded PPI_CHG_CH11_Excluded
#define PPI_CHG1_CH11_Included PPI_CHG_CH11_Included
#define PPI_CHG1_CH10_Pos PPI_CHG_CH10_Pos
#define PPI_CHG1_CH10_Msk PPI_CHG_CH10_Msk
#define PPI_CHG1_CH10_Excluded PPI_CHG_CH10_Excluded
#define PPI_CHG1_CH10_Included PPI_CHG_CH10_Included
#define PPI_CHG1_CH9_Pos PPI_CHG_CH9_Pos
#define PPI_CHG1_CH9_Msk PPI_CHG_CH9_Msk
#define PPI_CHG1_CH9_Excluded PPI_CHG_CH9_Excluded
#define PPI_CHG1_CH9_Included PPI_CHG_CH9_Included
#define PPI_CHG1_CH8_Pos PPI_CHG_CH8_Pos
#define PPI_CHG1_CH8_Msk PPI_CHG_CH8_Msk
#define PPI_CHG1_CH8_Excluded PPI_CHG_CH8_Excluded
#define PPI_CHG1_CH8_Included PPI_CHG_CH8_Included
#define PPI_CHG1_CH7_Pos PPI_CHG_CH7_Pos
#define PPI_CHG1_CH7_Msk PPI_CHG_CH7_Msk
#define PPI_CHG1_CH7_Excluded PPI_CHG_CH7_Excluded
#define PPI_CHG1_CH7_Included PPI_CHG_CH7_Included
#define PPI_CHG1_CH6_Pos PPI_CHG_CH6_Pos
#define PPI_CHG1_CH6_Msk PPI_CHG_CH6_Msk
#define PPI_CHG1_CH6_Excluded PPI_CHG_CH6_Excluded
#define PPI_CHG1_CH6_Included PPI_CHG_CH6_Included
#define PPI_CHG1_CH5_Pos PPI_CHG_CH5_Pos
#define PPI_CHG1_CH5_Msk PPI_CHG_CH5_Msk
#define PPI_CHG1_CH5_Excluded PPI_CHG_CH5_Excluded
#define PPI_CHG1_CH5_Included PPI_CHG_CH5_Included
#define PPI_CHG1_CH4_Pos PPI_CHG_CH4_Pos
#define PPI_CHG1_CH4_Msk PPI_CHG_CH4_Msk
#define PPI_CHG1_CH4_Excluded PPI_CHG_CH4_Excluded
#define PPI_CHG1_CH4_Included PPI_CHG_CH4_Included
#define PPI_CHG1_CH3_Pos PPI_CHG_CH3_Pos
#define PPI_CHG1_CH3_Msk PPI_CHG_CH3_Msk
#define PPI_CHG1_CH3_Excluded PPI_CHG_CH3_Excluded
#define PPI_CHG1_CH3_Included PPI_CHG_CH3_Included
#define PPI_CHG1_CH2_Pos PPI_CHG_CH2_Pos
#define PPI_CHG1_CH2_Msk PPI_CHG_CH2_Msk
#define PPI_CHG1_CH2_Excluded PPI_CHG_CH2_Excluded
#define PPI_CHG1_CH2_Included PPI_CHG_CH2_Included
#define PPI_CHG1_CH1_Pos PPI_CHG_CH1_Pos
#define PPI_CHG1_CH1_Msk PPI_CHG_CH1_Msk
#define PPI_CHG1_CH1_Excluded PPI_CHG_CH1_Excluded
#define PPI_CHG1_CH1_Included PPI_CHG_CH1_Included
#define PPI_CHG1_CH0_Pos PPI_CHG_CH0_Pos
#define PPI_CHG1_CH0_Msk PPI_CHG_CH0_Msk
#define PPI_CHG1_CH0_Excluded PPI_CHG_CH0_Excluded
#define PPI_CHG1_CH0_Included PPI_CHG_CH0_Included
#define PPI_CHG2_CH15_Pos PPI_CHG_CH15_Pos
#define PPI_CHG2_CH15_Msk PPI_CHG_CH15_Msk
#define PPI_CHG2_CH15_Excluded PPI_CHG_CH15_Excluded
#define PPI_CHG2_CH15_Included PPI_CHG_CH15_Included
#define PPI_CHG2_CH14_Pos PPI_CHG_CH14_Pos
#define PPI_CHG2_CH14_Msk PPI_CHG_CH14_Msk
#define PPI_CHG2_CH14_Excluded PPI_CHG_CH14_Excluded
#define PPI_CHG2_CH14_Included PPI_CHG_CH14_Included
#define PPI_CHG2_CH13_Pos PPI_CHG_CH13_Pos
#define PPI_CHG2_CH13_Msk PPI_CHG_CH13_Msk
#define PPI_CHG2_CH13_Excluded PPI_CHG_CH13_Excluded
#define PPI_CHG2_CH13_Included PPI_CHG_CH13_Included
#define PPI_CHG2_CH12_Pos PPI_CHG_CH12_Pos
#define PPI_CHG2_CH12_Msk PPI_CHG_CH12_Msk
#define PPI_CHG2_CH12_Excluded PPI_CHG_CH12_Excluded
#define PPI_CHG2_CH12_Included PPI_CHG_CH12_Included
#define PPI_CHG2_CH11_Pos PPI_CHG_CH11_Pos
#define PPI_CHG2_CH11_Msk PPI_CHG_CH11_Msk
#define PPI_CHG2_CH11_Excluded PPI_CHG_CH11_Excluded
#define PPI_CHG2_CH11_Included PPI_CHG_CH11_Included
#define PPI_CHG2_CH10_Pos PPI_CHG_CH10_Pos
#define PPI_CHG2_CH10_Msk PPI_CHG_CH10_Msk
#define PPI_CHG2_CH10_Excluded PPI_CHG_CH10_Excluded
#define PPI_CHG2_CH10_Included PPI_CHG_CH10_Included
#define PPI_CHG2_CH9_Pos PPI_CHG_CH9_Pos
#define PPI_CHG2_CH9_Msk PPI_CHG_CH9_Msk
#define PPI_CHG2_CH9_Excluded PPI_CHG_CH9_Excluded
#define PPI_CHG2_CH9_Included PPI_CHG_CH9_Included
#define PPI_CHG2_CH8_Pos PPI_CHG_CH8_Pos
#define PPI_CHG2_CH8_Msk PPI_CHG_CH8_Msk
#define PPI_CHG2_CH8_Excluded PPI_CHG_CH8_Excluded
#define PPI_CHG2_CH8_Included PPI_CHG_CH8_Included
#define PPI_CHG2_CH7_Pos PPI_CHG_CH7_Pos
#define PPI_CHG2_CH7_Msk PPI_CHG_CH7_Msk
#define PPI_CHG2_CH7_Excluded PPI_CHG_CH7_Excluded
#define PPI_CHG2_CH7_Included PPI_CHG_CH7_Included
#define PPI_CHG2_CH6_Pos PPI_CHG_CH6_Pos
#define PPI_CHG2_CH6_Msk PPI_CHG_CH6_Msk
#define PPI_CHG2_CH6_Excluded PPI_CHG_CH6_Excluded
#define PPI_CHG2_CH6_Included PPI_CHG_CH6_Included
#define PPI_CHG2_CH5_Pos PPI_CHG_CH5_Pos
#define PPI_CHG2_CH5_Msk PPI_CHG_CH5_Msk
#define PPI_CHG2_CH5_Excluded PPI_CHG_CH5_Excluded
#define PPI_CHG2_CH5_Included PPI_CHG_CH5_Included
#define PPI_CHG2_CH4_Pos PPI_CHG_CH4_Pos
#define PPI_CHG2_CH4_Msk PPI_CHG_CH4_Msk
#define PPI_CHG2_CH4_Excluded PPI_CHG_CH4_Excluded
#define PPI_CHG2_CH4_Included PPI_CHG_CH4_Included
#define PPI_CHG2_CH3_Pos PPI_CHG_CH3_Pos
#define PPI_CHG2_CH3_Msk PPI_CHG_CH3_Msk
#define PPI_CHG2_CH3_Excluded PPI_CHG_CH3_Excluded
#define PPI_CHG2_CH3_Included PPI_CHG_CH3_Included
#define PPI_CHG2_CH2_Pos PPI_CHG_CH2_Pos
#define PPI_CHG2_CH2_Msk PPI_CHG_CH2_Msk
#define PPI_CHG2_CH2_Excluded PPI_CHG_CH2_Excluded
#define PPI_CHG2_CH2_Included PPI_CHG_CH2_Included
#define PPI_CHG2_CH1_Pos PPI_CHG_CH1_Pos
#define PPI_CHG2_CH1_Msk PPI_CHG_CH1_Msk
#define PPI_CHG2_CH1_Excluded PPI_CHG_CH1_Excluded
#define PPI_CHG2_CH1_Included PPI_CHG_CH1_Included
#define PPI_CHG2_CH0_Pos PPI_CHG_CH0_Pos
#define PPI_CHG2_CH0_Msk PPI_CHG_CH0_Msk
#define PPI_CHG2_CH0_Excluded PPI_CHG_CH0_Excluded
#define PPI_CHG2_CH0_Included PPI_CHG_CH0_Included
#define PPI_CHG3_CH15_Pos PPI_CHG_CH15_Pos
#define PPI_CHG3_CH15_Msk PPI_CHG_CH15_Msk
#define PPI_CHG3_CH15_Excluded PPI_CHG_CH15_Excluded
#define PPI_CHG3_CH15_Included PPI_CHG_CH15_Included
#define PPI_CHG3_CH14_Pos PPI_CHG_CH14_Pos
#define PPI_CHG3_CH14_Msk PPI_CHG_CH14_Msk
#define PPI_CHG3_CH14_Excluded PPI_CHG_CH14_Excluded
#define PPI_CHG3_CH14_Included PPI_CHG_CH14_Included
#define PPI_CHG3_CH13_Pos PPI_CHG_CH13_Pos
#define PPI_CHG3_CH13_Msk PPI_CHG_CH13_Msk
#define PPI_CHG3_CH13_Excluded PPI_CHG_CH13_Excluded
#define PPI_CHG3_CH13_Included PPI_CHG_CH13_Included
#define PPI_CHG3_CH12_Pos PPI_CHG_CH12_Pos
#define PPI_CHG3_CH12_Msk PPI_CHG_CH12_Msk
#define PPI_CHG3_CH12_Excluded PPI_CHG_CH12_Excluded
#define PPI_CHG3_CH12_Included PPI_CHG_CH12_Included
#define PPI_CHG3_CH11_Pos PPI_CHG_CH11_Pos
#define PPI_CHG3_CH11_Msk PPI_CHG_CH11_Msk
#define PPI_CHG3_CH11_Excluded PPI_CHG_CH11_Excluded
#define PPI_CHG3_CH11_Included PPI_CHG_CH11_Included
#define PPI_CHG3_CH10_Pos PPI_CHG_CH10_Pos
#define PPI_CHG3_CH10_Msk PPI_CHG_CH10_Msk
#define PPI_CHG3_CH10_Excluded PPI_CHG_CH10_Excluded
#define PPI_CHG3_CH10_Included PPI_CHG_CH10_Included
#define PPI_CHG3_CH9_Pos PPI_CHG_CH9_Pos
#define PPI_CHG3_CH9_Msk PPI_CHG_CH9_Msk
#define PPI_CHG3_CH9_Excluded PPI_CHG_CH9_Excluded
#define PPI_CHG3_CH9_Included PPI_CHG_CH9_Included
#define PPI_CHG3_CH8_Pos PPI_CHG_CH8_Pos
#define PPI_CHG3_CH8_Msk PPI_CHG_CH8_Msk
#define PPI_CHG3_CH8_Excluded PPI_CHG_CH8_Excluded
#define PPI_CHG3_CH8_Included PPI_CHG_CH8_Included
#define PPI_CHG3_CH7_Pos PPI_CHG_CH7_Pos
#define PPI_CHG3_CH7_Msk PPI_CHG_CH7_Msk
#define PPI_CHG3_CH7_Excluded PPI_CHG_CH7_Excluded
#define PPI_CHG3_CH7_Included PPI_CHG_CH7_Included
#define PPI_CHG3_CH6_Pos PPI_CHG_CH6_Pos
#define PPI_CHG3_CH6_Msk PPI_CHG_CH6_Msk
#define PPI_CHG3_CH6_Excluded PPI_CHG_CH6_Excluded
#define PPI_CHG3_CH6_Included PPI_CHG_CH6_Included
#define PPI_CHG3_CH5_Pos PPI_CHG_CH5_Pos
#define PPI_CHG3_CH5_Msk PPI_CHG_CH5_Msk
#define PPI_CHG3_CH5_Excluded PPI_CHG_CH5_Excluded
#define PPI_CHG3_CH5_Included PPI_CHG_CH5_Included
#define PPI_CHG3_CH4_Pos PPI_CHG_CH4_Pos
#define PPI_CHG3_CH4_Msk PPI_CHG_CH4_Msk
#define PPI_CHG3_CH4_Excluded PPI_CHG_CH4_Excluded
#define PPI_CHG3_CH4_Included PPI_CHG_CH4_Included
#define PPI_CHG3_CH3_Pos PPI_CHG_CH3_Pos
#define PPI_CHG3_CH3_Msk PPI_CHG_CH3_Msk
#define PPI_CHG3_CH3_Excluded PPI_CHG_CH3_Excluded
#define PPI_CHG3_CH3_Included PPI_CHG_CH3_Included
#define PPI_CHG3_CH2_Pos PPI_CHG_CH2_Pos
#define PPI_CHG3_CH2_Msk PPI_CHG_CH2_Msk
#define PPI_CHG3_CH2_Excluded PPI_CHG_CH2_Excluded
#define PPI_CHG3_CH2_Included PPI_CHG_CH2_Included
#define PPI_CHG3_CH1_Pos PPI_CHG_CH1_Pos
#define PPI_CHG3_CH1_Msk PPI_CHG_CH1_Msk
#define PPI_CHG3_CH1_Excluded PPI_CHG_CH1_Excluded
#define PPI_CHG3_CH1_Included PPI_CHG_CH1_Included
#define PPI_CHG3_CH0_Pos PPI_CHG_CH0_Pos
#define PPI_CHG3_CH0_Msk PPI_CHG_CH0_Msk
#define PPI_CHG3_CH0_Excluded PPI_CHG_CH0_Excluded
#define PPI_CHG3_CH0_Included PPI_CHG_CH0_Included
/*lint --flb "Leave library region" */
#endif /* NRF51_TO_NRF52_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,79 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 NRF52_NAME_CHANGE_H
#define NRF52_NAME_CHANGE_H
/*lint ++flb "Enter library region */
/* This file is given to prevent your SW from not compiling with the updates made to nrf52.h and
* nrf52_bitfields.h. The macros defined in this file were available previously. Do not use these
* macros on purpose. Use the ones defined in nrf52.h and nrf52_bitfields.h instead.
*/
/* I2S */
/* Several enumerations changed case. Adding old macros to keep compilation compatibility. */
#define I2S_ENABLE_ENABLE_DISABLE I2S_ENABLE_ENABLE_Disabled
#define I2S_ENABLE_ENABLE_ENABLE I2S_ENABLE_ENABLE_Enabled
#define I2S_CONFIG_MODE_MODE_MASTER I2S_CONFIG_MODE_MODE_Master
#define I2S_CONFIG_MODE_MODE_SLAVE I2S_CONFIG_MODE_MODE_Slave
#define I2S_CONFIG_RXEN_RXEN_DISABLE I2S_CONFIG_RXEN_RXEN_Disabled
#define I2S_CONFIG_RXEN_RXEN_ENABLE I2S_CONFIG_RXEN_RXEN_Enabled
#define I2S_CONFIG_TXEN_TXEN_DISABLE I2S_CONFIG_TXEN_TXEN_Disabled
#define I2S_CONFIG_TXEN_TXEN_ENABLE I2S_CONFIG_TXEN_TXEN_Enabled
#define I2S_CONFIG_MCKEN_MCKEN_DISABLE I2S_CONFIG_MCKEN_MCKEN_Disabled
#define I2S_CONFIG_MCKEN_MCKEN_ENABLE I2S_CONFIG_MCKEN_MCKEN_Enabled
#define I2S_CONFIG_SWIDTH_SWIDTH_8BIT I2S_CONFIG_SWIDTH_SWIDTH_8Bit
#define I2S_CONFIG_SWIDTH_SWIDTH_16BIT I2S_CONFIG_SWIDTH_SWIDTH_16Bit
#define I2S_CONFIG_SWIDTH_SWIDTH_24BIT I2S_CONFIG_SWIDTH_SWIDTH_24Bit
#define I2S_CONFIG_ALIGN_ALIGN_LEFT I2S_CONFIG_ALIGN_ALIGN_Left
#define I2S_CONFIG_ALIGN_ALIGN_RIGHT I2S_CONFIG_ALIGN_ALIGN_Right
#define I2S_CONFIG_FORMAT_FORMAT_ALIGNED I2S_CONFIG_FORMAT_FORMAT_Aligned
#define I2S_CONFIG_CHANNELS_CHANNELS_STEREO I2S_CONFIG_CHANNELS_CHANNELS_Stereo
#define I2S_CONFIG_CHANNELS_CHANNELS_LEFT I2S_CONFIG_CHANNELS_CHANNELS_Left
#define I2S_CONFIG_CHANNELS_CHANNELS_RIGHT I2S_CONFIG_CHANNELS_CHANNELS_Right
/*lint --flb "Leave library region" */
#endif /* NRF52_NAME_CHANGE_H */

View File

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

View File

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

View File

@ -1,506 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_drv_clock.h"
#include "nrf_error.h"
#include "nordic_common.h"
#ifdef SOFTDEVICE_PRESENT
#include "nrf_sdm.h"
#include "nrf_soc.h"
#include "app_util_platform.h"
#else
#include "app_util_platform.h"
#endif // SOFTDEVICE_PRESENT
/*lint -save -e652 */
#define NRF_CLOCK_LFCLK_RC CLOCK_LFCLKSRC_SRC_RC
#define NRF_CLOCK_LFCLK_Xtal CLOCK_LFCLKSRC_SRC_Xtal
#define NRF_CLOCK_LFCLK_Synth CLOCK_LFCLKSRC_SRC_Synth
/*lint -restore */
#define INT_MAX 0xFFFFFFFF
#if (CLOCK_CONFIG_LF_SRC == NRF_CLOCK_LFCLK_RC) && !defined(SOFTDEVICE_PRESENT)
#define CALIBRATION_SUPPORT 1
#else
#define CALIBRATION_SUPPORT 0
#endif
typedef enum
{
CAL_STATE_IDLE,
CAL_STATE_CT,
CAL_STATE_HFCLK_REQ,
CAL_STATE_CAL,
CAL_STATE_ABORT,
} nrf_drv_clock_cal_state_t;
/**@brief CLOCK control block. */
typedef struct
{
volatile uint32_t hfclk_requests; /*< High-frequency clock request counter. */
volatile nrf_drv_clock_handler_item_t * p_hf_head;
bool module_initialized; /*< Indicate the state of module */
volatile bool hfclk_on; /*< High-frequency clock state. */
#ifndef SOFTDEVICE_PRESENT
volatile bool lfclk_on; /*< Low-frequency clock state. */
uint32_t lfclk_requests; /*< Low-frequency clock request counter. */
volatile nrf_drv_clock_handler_item_t * p_lf_head;
#if CALIBRATION_SUPPORT
nrf_drv_clock_handler_item_t cal_hfclk_started_handler_item;
nrf_drv_clock_event_handler_t cal_done_handler;
volatile nrf_drv_clock_cal_state_t cal_state;
#endif //CALIBRATION_SUPPORT
#endif //SOFTDEVICE_PRESENT
}nrf_drv_clock_cb_t;
static nrf_drv_clock_cb_t m_clock_cb;
#ifndef SOFTDEVICE_PRESENT
/**@brief Function for starting LFCLK. This function will return immediately without waiting for start.
*/
static void lfclk_start(void)
{
nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED);
nrf_clock_int_enable(NRF_CLOCK_INT_LF_STARTED_MASK);
nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTART);
}
/**@brief Function for stopping LFCLK and calibration (if it was set up).
*/
static void lfclk_stop(void)
{
#if CALIBRATION_SUPPORT
(void)nrf_drv_clock_calibration_abort();
#endif //CALIBRATION_SUPPORT
nrf_clock_task_trigger(NRF_CLOCK_TASK_LFCLKSTOP);
while (nrf_clock_lf_is_running())
{}
}
#endif
static void hfclk_start(void)
{
#ifndef SOFTDEVICE_PRESENT
nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED);
nrf_clock_int_enable(NRF_CLOCK_INT_HF_STARTED_MASK);
nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTART);
#else
UNUSED_VARIABLE(sd_clock_hfclk_request());
#endif
}
static void hfclk_stop(void)
{
#ifndef SOFTDEVICE_PRESENT
nrf_clock_task_trigger(NRF_CLOCK_TASK_HFCLKSTOP);
while (nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY))
{}
#else
UNUSED_VARIABLE(sd_clock_hfclk_release());
#endif
}
ret_code_t nrf_drv_clock_init(void)
{
uint32_t result = NRF_SUCCESS;
if (m_clock_cb.module_initialized)
{
return MODULE_ALREADY_INITIALIZED;
}
m_clock_cb.p_hf_head = NULL;
m_clock_cb.hfclk_requests = 0;
#ifndef SOFTDEVICE_PRESENT
m_clock_cb.p_lf_head = NULL;
m_clock_cb.lfclk_requests = 0;
nrf_clock_xtalfreq_set(CLOCK_CONFIG_XTAL_FREQ);
nrf_clock_lf_src_set((nrf_clock_lfclk_t)CLOCK_CONFIG_LF_SRC);
nrf_drv_common_irq_enable(POWER_CLOCK_IRQn, CLOCK_CONFIG_IRQ_PRIORITY);
#if CALIBRATION_SUPPORT
m_clock_cb.cal_state = CAL_STATE_IDLE;
#endif // CALIBRATION_SUPPORT
#else // SOFTDEVICE_PRESENT
uint8_t is_enabled;
result = sd_softdevice_is_enabled(&is_enabled);
if((result == NRF_SUCCESS) && !is_enabled)
{
result = NRF_ERROR_SOFTDEVICE_NOT_ENABLED;
}
#endif // SOFTDEVICE_PRESENT
m_clock_cb.module_initialized = true;
return result;
}
void nrf_drv_clock_uninit(void)
{
ASSERT(m_clock_cb.module_initialized);
#ifndef SOFTDEVICE_PRESENT
nrf_drv_common_irq_disable(POWER_CLOCK_IRQn);
nrf_clock_int_disable(0xFFFFFFFF);
lfclk_stop();
#endif
hfclk_stop();
m_clock_cb.module_initialized = false;
}
static void item_enqueue(nrf_drv_clock_handler_item_t ** p_head,
nrf_drv_clock_handler_item_t * p_item)
{
if (*p_head)
{
p_item->p_next = *p_head;
*p_head = p_item;
}
else
{
p_item->p_next = NULL;
*p_head = p_item;
}
}
static nrf_drv_clock_handler_item_t * item_dequeue(nrf_drv_clock_handler_item_t ** p_head)
{
nrf_drv_clock_handler_item_t * p_item = *p_head;
if (p_item)
{
*p_head = p_item->p_next;
}
return p_item;
}
void nrf_drv_clock_lfclk_request(nrf_drv_clock_handler_item_t * p_handler_item)
{
ASSERT(m_clock_cb.module_initialized);
#ifndef SOFTDEVICE_PRESENT
ASSERT(m_clock_cb.lfclk_requests != INT_MAX);
CRITICAL_REGION_ENTER();
if (m_clock_cb.lfclk_on)
{
if (p_handler_item)
{
p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_LFCLK_STARTED);
}
}
else
{
if (p_handler_item)
{
item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head, p_handler_item);
}
if (m_clock_cb.lfclk_requests == 0)
{
lfclk_start();
}
}
m_clock_cb.lfclk_requests++;
CRITICAL_REGION_EXIT();
#else
if (p_handler_item)
{
p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_LFCLK_STARTED);
}
#endif // SOFTDEVICE_PRESENT
}
void nrf_drv_clock_lfclk_release(void)
{
ASSERT(m_clock_cb.module_initialized);
#ifndef SOFTDEVICE_PRESENT
ASSERT(m_clock_cb.lfclk_requests > 0);
CRITICAL_REGION_ENTER();
m_clock_cb.lfclk_requests--;
if (m_clock_cb.lfclk_requests == 0)
{
lfclk_stop();
m_clock_cb.lfclk_on = false;
m_clock_cb.p_lf_head = NULL;
}
CRITICAL_REGION_EXIT();
#endif // SOFTDEVICE_PRESENT
}
bool nrf_drv_clock_lfclk_is_running(void)
{
ASSERT(m_clock_cb.module_initialized);
bool result;
#ifndef SOFTDEVICE_PRESENT
result = nrf_clock_lf_is_running();
#else
result = true;
#endif
return result;
}
void nrf_drv_clock_hfclk_request(nrf_drv_clock_handler_item_t * p_handler_item)
{
ASSERT(m_clock_cb.module_initialized);
ASSERT(m_clock_cb.hfclk_requests != INT_MAX);
CRITICAL_REGION_ENTER();
if (m_clock_cb.hfclk_on)
{
if (p_handler_item)
{
p_handler_item->event_handler(NRF_DRV_CLOCK_EVT_HFCLK_STARTED);
}
}
else
{
if (p_handler_item)
{
item_enqueue((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head, p_handler_item);
}
if (m_clock_cb.hfclk_requests == 0)
{
hfclk_start();
}
}
m_clock_cb.hfclk_requests++;
CRITICAL_REGION_EXIT();
}
void nrf_drv_clock_hfclk_release(void)
{
ASSERT(m_clock_cb.module_initialized);
ASSERT(m_clock_cb.hfclk_requests > 0);
//disable interrupts CLOCK or SoftDevice events
CRITICAL_REGION_ENTER();
m_clock_cb.hfclk_requests--;
if (m_clock_cb.hfclk_requests == 0)
{
hfclk_stop();
m_clock_cb.hfclk_on = false;
m_clock_cb.p_hf_head = NULL;
}
CRITICAL_REGION_EXIT();
//enable interrupts CLOCK or SoftDevice events
}
bool nrf_drv_clock_hfclk_is_running(void)
{
bool result;
ASSERT(m_clock_cb.module_initialized);
#ifndef SOFTDEVICE_PRESENT
result = nrf_clock_hf_is_running(NRF_CLOCK_HFCLK_HIGH_ACCURACY);
#else
uint32_t is_running;
UNUSED_VARIABLE(sd_clock_hfclk_is_running(&is_running));
result = is_running ? true : false;
#endif
return result;
}
#if CALIBRATION_SUPPORT
static void clock_calibration_hf_started(nrf_drv_clock_evt_type_t event)
{
if (m_clock_cb.cal_state == CAL_STATE_ABORT)
{
nrf_drv_clock_hfclk_release();
m_clock_cb.cal_state = CAL_STATE_IDLE;
if (m_clock_cb.cal_done_handler)
{
m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED);
}
}
else
{
nrf_clock_int_enable(NRF_CLOCK_INT_DONE_MASK);
m_clock_cb.cal_state = CAL_STATE_CAL;
nrf_clock_task_trigger(NRF_CLOCK_TASK_CAL);
}
}
#endif
ret_code_t nrf_drv_clock_calibration_start(uint8_t interval, nrf_drv_clock_event_handler_t handler)
{
#if CALIBRATION_SUPPORT
ASSERT(m_clock_cb.cal_state == CAL_STATE_IDLE);
ret_code_t ret = NRF_SUCCESS;
if (m_clock_cb.lfclk_on == false)
{
ret = NRF_ERROR_INVALID_STATE;
}
else if (m_clock_cb.cal_state == CAL_STATE_IDLE)
{
m_clock_cb.cal_done_handler = handler;
m_clock_cb.cal_hfclk_started_handler_item.event_handler = clock_calibration_hf_started;
if (interval == 0)
{
m_clock_cb.cal_state = CAL_STATE_HFCLK_REQ;
nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item);
}
else
{
m_clock_cb.cal_state = CAL_STATE_CT;
nrf_clock_cal_timer_timeout_set(interval);
nrf_clock_int_enable(NRF_CLOCK_INT_CTTO_MASK);
nrf_clock_task_trigger(NRF_CLOCK_TASK_CTSTART);
}
}
else
{
ret = NRF_ERROR_BUSY;
}
return ret;
#else //CALIBRATION_SUPPORT
return NRF_ERROR_FORBIDDEN;
#endif
}
ret_code_t nrf_drv_clock_calibration_abort(void)
{
#if CALIBRATION_SUPPORT
CRITICAL_REGION_ENTER();
switch(m_clock_cb.cal_state)
{
case CAL_STATE_CT:
nrf_clock_int_disable(NRF_CLOCK_INT_CTTO_MASK);
nrf_clock_task_trigger(NRF_CLOCK_TASK_CTSTOP);
m_clock_cb.cal_state = CAL_STATE_IDLE;
if (m_clock_cb.cal_done_handler)
{
m_clock_cb.cal_done_handler(NRF_DRV_CLOCK_EVT_CAL_ABORTED);
}
break;
case CAL_STATE_HFCLK_REQ:
/* fall through. */
case CAL_STATE_CAL:
m_clock_cb.cal_state = CAL_STATE_ABORT;
break;
default:
break;
}
CRITICAL_REGION_EXIT();
return NRF_SUCCESS;
#else //CALIBRATION_SUPPORT
return NRF_ERROR_FORBIDDEN;
#endif
}
ret_code_t nrf_drv_clock_is_calibrating(bool * p_is_calibrating)
{
#if CALIBRATION_SUPPORT
ASSERT(m_clock_cb.module_initialized);
*p_is_calibrating = (m_clock_cb.cal_state != CAL_STATE_IDLE);
return NRF_SUCCESS;
#else //CALIBRATION_SUPPORT
return NRF_ERROR_FORBIDDEN;
#endif
}
static __INLINE void clock_clk_started_notify(nrf_drv_clock_handler_item_t **p_head,
nrf_drv_clock_evt_type_t evt_type)
{
while(1)
{
nrf_drv_clock_handler_item_t * p_item = item_dequeue(p_head);
if (p_item)
{
p_item->event_handler(evt_type);
}
else
{
break;
}
}
}
#ifndef SOFTDEVICE_PRESENT
void POWER_CLOCK_IRQHandler(void)
{
if (nrf_clock_event_check(NRF_CLOCK_EVENT_HFCLKSTARTED))
{
nrf_clock_event_clear(NRF_CLOCK_EVENT_HFCLKSTARTED);
nrf_clock_int_disable(NRF_CLOCK_INT_HF_STARTED_MASK);
m_clock_cb.hfclk_on = true;
clock_clk_started_notify((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head, NRF_DRV_CLOCK_EVT_HFCLK_STARTED);
}
if (nrf_clock_event_check(NRF_CLOCK_EVENT_LFCLKSTARTED))
{
nrf_clock_event_clear(NRF_CLOCK_EVENT_LFCLKSTARTED);
nrf_clock_int_disable(NRF_CLOCK_INT_LF_STARTED_MASK);
m_clock_cb.lfclk_on = true;
clock_clk_started_notify((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_lf_head, NRF_DRV_CLOCK_EVT_LFCLK_STARTED);
}
#if CALIBRATION_SUPPORT
if (nrf_clock_event_check(NRF_CLOCK_EVENT_CTTO))
{
nrf_clock_event_clear(NRF_CLOCK_EVENT_CTTO);
nrf_clock_int_disable(NRF_CLOCK_INT_CTTO_MASK);
nrf_drv_clock_hfclk_request(&m_clock_cb.cal_hfclk_started_handler_item);
}
if (nrf_clock_event_check(NRF_CLOCK_EVENT_DONE))
{
nrf_clock_event_clear(NRF_CLOCK_EVENT_DONE);
nrf_clock_int_disable(NRF_CLOCK_INT_DONE_MASK);
nrf_drv_clock_hfclk_release();
nrf_drv_clock_evt_type_t evt_type = (m_clock_cb.cal_state == CAL_STATE_ABORT) ?
NRF_DRV_CLOCK_EVT_CAL_ABORTED : NRF_DRV_CLOCK_EVT_CAL_DONE;
m_clock_cb.cal_state = CAL_STATE_IDLE;
if (m_clock_cb.cal_done_handler)
{
m_clock_cb.cal_done_handler(evt_type);
}
}
#endif //CALIBRATION_SUPPORT
}
#else
void nrf_drv_clock_on_soc_event(uint32_t evt_id)
{
if (evt_id == NRF_EVT_HFCLKSTARTED)
{
clock_clk_started_notify((nrf_drv_clock_handler_item_t **)&m_clock_cb.p_hf_head, NRF_DRV_CLOCK_EVT_HFCLK_STARTED);
}
}
#endif // SOFTDEVICE_PRESENT
#undef NRF_CLOCK_LFCLK_RC
#undef NRF_CLOCK_LFCLK_Xtal
#undef NRF_CLOCK_LFCLK_Synth

View File

@ -1,273 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 <stdbool.h>
#include <stdint.h>
#include "sdk_errors.h"
#include "nrf_assert.h"
#include "nrf_clock.h"
#include "nrf_drv_config.h"
#include "nrf_drv_common.h"
/**
*
* @addtogroup nrf_clock Clock HAL and driver
* @ingroup nrf_drivers
* @brief Clock APIs.
* @details The clock HAL provides basic APIs for accessing the registers of the clock.
* The clock driver provides APIs on a higher level.
*
* @defgroup nrf_clock_drv Clock driver
* @{
* @ingroup nrf_clock
* @brief Driver for managing the low-frequency clock (LFCLK) and the high-frequency clock (HFCLK).
*/
/**
* @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 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 MODULE_ALREADY_INITIALIZED If the driver was already initialized.
* @retval NRF_ERROR_SOFTDEVICE_NOT_ENABLED If the SoftDevice was not enabled.
*/
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);
/**
* @brief Function called by the SoftDevice handler if an @ref nrf_soc event is received from the SoftDevice.
*/
#ifdef SOFTDEVICE_PRESENT
void nrf_drv_clock_on_soc_event(uint32_t evt_id);
#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
/*lint --flb "Leave library region" */
#endif // NRF_CLOCK_H__

View File

@ -1,239 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 <stddef.h>
#include "nrf_drv_common.h"
#include "nrf_assert.h"
#include "app_util_platform.h"
#ifdef SOFTDEVICE_PRESENT
#include "nrf_soc.h"
#endif
#if PERIPHERAL_RESOURCE_SHARING_ENABLED
typedef struct {
nrf_drv_irq_handler_t handler;
bool acquired;
} shared_resource_t;
// SPIM0, SPIS0, SPI0, TWIM0, TWIS0, TWI0
#if (SPI0_ENABLED || SPIS0_ENABLED || TWI0_ENABLED || TWIS0_ENABLED)
#define SERIAL_BOX_0_IN_USE
// [this checking may need a different form in unit tests, hence macro]
#ifndef IS_SERIAL_BOX_0
#define IS_SERIAL_BOX_0(p_per_base) (p_per_base == NRF_SPI0)
#endif
static shared_resource_t m_serial_box_0 = { .acquired = false };
void SPI0_TWI0_IRQHandler(void)
{
ASSERT(m_serial_box_0.handler);
m_serial_box_0.handler();
}
#endif // (SPI0_ENABLED || SPIS0_ENABLED || TWI0_ENABLED || TWIS0_ENABLED)
// SPIM1, SPIS1, SPI1, TWIM1, TWIS1, TWI1
#if (SPI1_ENABLED || SPIS1_ENABLED || TWI1_ENABLED || TWIS1_ENABLED)
#define SERIAL_BOX_1_IN_USE
// [this checking may need a different form in unit tests, hence macro]
#ifndef IS_SERIAL_BOX_1
#define IS_SERIAL_BOX_1(p_per_base) (p_per_base == NRF_SPI1)
#endif
static shared_resource_t m_serial_box_1 = { .acquired = false };
void SPI1_TWI1_IRQHandler(void)
{
ASSERT(m_serial_box_1.handler);
m_serial_box_1.handler();
}
#endif // (SPI1_ENABLED || SPIS1_ENABLED || TWI1_ENABLED || TWIS1_ENABLED)
// SPIM2, SPIS2, SPI2
#if (SPI2_ENABLED || SPIS2_ENABLED)
#define SERIAL_BOX_2_IN_USE
// [this checking may need a different form in unit tests, hence macro]
#ifndef IS_SERIAL_BOX_2
#define IS_SERIAL_BOX_2(p_per_base) (p_per_base == NRF_SPI2)
#endif
static shared_resource_t m_serial_box_2 = { .acquired = false };
void SPIM2_SPIS2_SPI2_IRQHandler(void)
{
ASSERT(m_serial_box_2.handler);
m_serial_box_2.handler();
}
#endif // (SPI2_ENABLED || SPIS2_ENABLED)
// COMP, LPCOMP
#if (COMP_ENABLED || LPCOMP_ENABLED)
#define COMP_LPCOMP_IN_USE
#ifndef IS_COMP_LPCOMP
#define IS_COMP_LPCOMP(p_per_base) ((p_per_base) == NRF_LPCOMP)
#endif
static shared_resource_t m_comp_lpcomp = { .acquired = false };
void LPCOMP_IRQHandler(void)
{
ASSERT(m_comp_lpcomp.handler);
m_comp_lpcomp.handler();
}
#endif // (COMP_ENABLED || LPCOMP_ENABLED)
#if defined(SERIAL_BOX_0_IN_USE) || \
defined(SERIAL_BOX_1_IN_USE) || \
defined(SERIAL_BOX_2_IN_USE) || \
defined(COMP_LPCOMP_IN_USE)
static ret_code_t acquire_shared_resource(shared_resource_t * p_resource,
nrf_drv_irq_handler_t handler)
{
bool busy = false;
CRITICAL_REGION_ENTER();
if (p_resource->acquired)
{
busy = true;
}
else
{
p_resource->acquired = true;
}
CRITICAL_REGION_EXIT();
if (busy)
{
return NRF_ERROR_BUSY;
}
p_resource->handler = handler;
return NRF_SUCCESS;
}
#endif
ret_code_t nrf_drv_common_per_res_acquire(void const * p_per_base,
nrf_drv_irq_handler_t handler)
{
#ifdef SERIAL_BOX_0_IN_USE
if (IS_SERIAL_BOX_0(p_per_base))
{
return acquire_shared_resource(&m_serial_box_0, handler);
}
#endif
#ifdef SERIAL_BOX_1_IN_USE
if (IS_SERIAL_BOX_1(p_per_base))
{
return acquire_shared_resource(&m_serial_box_1, handler);
}
#endif
#ifdef SERIAL_BOX_2_IN_USE
if (IS_SERIAL_BOX_2(p_per_base))
{
return acquire_shared_resource(&m_serial_box_2, handler);
}
#endif
#ifdef COMP_LPCOMP_IN_USE
if (IS_COMP_LPCOMP(p_per_base))
{
return acquire_shared_resource(&m_comp_lpcomp, handler);
}
#endif
return NRF_ERROR_INVALID_PARAM;
}
void nrf_drv_common_per_res_release(void const * p_per_base)
{
#ifdef SERIAL_BOX_0_IN_USE
if (IS_SERIAL_BOX_0(p_per_base))
{
m_serial_box_0.acquired = false;
}
else
#endif
#ifdef SERIAL_BOX_1_IN_USE
if (IS_SERIAL_BOX_1(p_per_base))
{
m_serial_box_1.acquired = false;
}
else
#endif
#ifdef SERIAL_BOX_2_IN_USE
if (IS_SERIAL_BOX_2(p_per_base))
{
m_serial_box_2.acquired = false;
}
else
#endif
#ifdef COMP_LPCOMP_IN_USE
if (IS_COMP_LPCOMP(p_per_base))
{
m_comp_lpcomp.acquired = false;
}
else
#endif
{}
}
#endif // PERIPHERAL_RESOURCE_SHARING_ENABLED
void nrf_drv_common_irq_enable(IRQn_Type IRQn, uint8_t priority)
{
#ifdef SOFTDEVICE_PRESENT
#ifdef NRF51
ASSERT((priority == APP_IRQ_PRIORITY_LOW) || (priority == APP_IRQ_PRIORITY_HIGH));
#elif defined(NRF52)
ASSERT((priority == APP_IRQ_PRIORITY_LOWEST) || (priority == APP_IRQ_PRIORITY_HIGH));
#endif
#endif
NVIC_SetPriority(IRQn, priority);
NVIC_ClearPendingIRQ(IRQn);
NVIC_EnableIRQ(IRQn);
}

View File

@ -1,221 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 <stdint.h>
#include <stdbool.h>
#include "nrf.h"
#include "sdk_errors.h"
#include "nrf_drv_config.h"
/**
* @brief Offset of event registers in every peripheral instance
*
* This is the offset where event registers start in the every peripheral.
*/
#define NRF_DRV_COMMON_EVREGS_OFFSET 0x100U
/**
* @brief Driver state.
*/
typedef enum
{
NRF_DRV_STATE_UNINITIALIZED, /**< Uninitialized. */
NRF_DRV_STATE_INITIALIZED, /**< Initialized but powered off. */
NRF_DRV_STATE_POWERED_ON
} nrf_drv_state_t;
/**
* @brief Driver power state selection.
*/
typedef enum
{
NRF_DRV_PWR_CTRL_ON, /**< Power on request. */
NRF_DRV_PWR_CTRL_OFF /**< Power off request. */
} nrf_drv_pwr_ctrl_t;
/**
* @brief IRQ handler type.
*/
typedef void (*nrf_drv_irq_handler_t)(void);
#if PERIPHERAL_RESOURCE_SHARING_ENABLED
/**
* @brief Function for acquiring shared peripheral resources associated with
* the specified peripheral.
*
* Certain resources and registers are shared among peripherals that have
* the same ID (for example: SPI0, SPIM0, SPIS0, TWI0, TWIM0, and TWIS0).
* Only one of them can be utilized at a given time. This function reserves
* proper resources to be used by the specified peripheral.
* If PERIPHERAL_RESOURCE_SHARING_ENABLED is set to a non-zero value, IRQ
* handlers for peripherals that are sharing resources with others are
* implemented by the nrf_drv_common module instead of individual drivers.
* The drivers must then specify their interrupt handling routines and
* register them by using this function.
*
* @param[in] p_per_base Requested peripheral base pointer.
* @param[in] handler Interrupt handler to register. May be NULL
* if interrupts are not used for the peripheral.
*
* @retval NRF_SUCCESS If resources were acquired successfully.
* @retval NRF_ERROR_BUSY If resources were already acquired.
* @retval NRF_ERROR_INVALID_PARAM If the specified peripheral is not enabled
* or the peripheral does not share resources
* with other peripherals.
*/
ret_code_t nrf_drv_common_per_res_acquire(void const * p_per_base,
nrf_drv_irq_handler_t handler);
/**
* @brief Function for releasing shared resources reserved previously by
* @ref nrf_drv_common_per_res_acquire() for the specified peripheral.
*
* @param[in] p_per_base Requested peripheral base pointer.
*/
void nrf_drv_common_per_res_release(void const * p_per_base);
#endif // PERIPHERAL_RESOURCE_SHARING_ENABLED
/**
* @brief Function sets priority and enables NVIC interrupt
*
* @note Function checks if correct priority is used when softdevice is present
*
* @param[in] IRQn Interrupt id
* @param[in] priority Interrupt priority
*/
void nrf_drv_common_irq_enable(IRQn_Type IRQn, uint8_t priority);
/**
* @brief Function disables NVIC interrupt
*
* @param[in] IRQn Interrupt id
*/
__STATIC_INLINE void nrf_drv_common_irq_disable(IRQn_Type IRQn);
/**
* @brief Convert bit position to event code
*
* Function for converting the bit position in INTEN register to event code
* that is equivalent to the offset of the event register from the beginning
* of peripheral instance.
*
* For example the result of this function can be casted directly to
* the types like @ref nrf_twis_event_t or @ref nrf_rng_events_t...
*
* @param bit Bit position in INTEN register
* @return Event code to be casted to the right enum type or to be used in functions like
* @ref nrf_rng_event_get
*
* @sa nrf_drv_event_to_bitpos
*/
__STATIC_INLINE uint32_t nrf_drv_bitpos_to_event(uint32_t bit);
/**
* @brief Convert event code to bit position
*
* This function can be used to get bit position in INTEN register from event code.
*
* @param event Event code that may be casted from enum values from types like
* @ref nrf_twis_event_t or @ref nrf_rng_events_t
* @return Bit position in INTEN register that corresponds to the given code.
*
* @sa nrf_drv_bitpos_to_event
*/
__STATIC_INLINE uint32_t nrf_drv_event_to_bitpos(uint32_t event);
/**
* @brief Get interrupt number connected with given instance
*
* Function returns interrupt number for a given instance of any peripheral.
* @param[in] pinst Pointer to peripheral registry
* @return Interrupt number
*/
__STATIC_INLINE IRQn_Type nrf_drv_get_IRQn(void const * const pinst);
/**
* @brief Check if given object is in RAM
*
* Function for analyzing if given location is placed in RAM.
* This function is used to determine if we have address that can be supported by EasyDMA.
* @param[in] ptr Pointer to the object
* @retval true Object is located in RAM
* @retval false Object is not located in RAM
*/
__STATIC_INLINE bool nrf_drv_is_in_RAM(void const * const ptr);
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE void nrf_drv_common_irq_disable(IRQn_Type IRQn)
{
NVIC_DisableIRQ(IRQn);
}
__STATIC_INLINE uint32_t nrf_drv_bitpos_to_event(uint32_t bit)
{
return NRF_DRV_COMMON_EVREGS_OFFSET + bit * sizeof(uint32_t);
}
__STATIC_INLINE uint32_t nrf_drv_event_to_bitpos(uint32_t event)
{
return (event - NRF_DRV_COMMON_EVREGS_OFFSET) / sizeof(uint32_t);
}
__STATIC_INLINE IRQn_Type nrf_drv_get_IRQn(void const * const pinst)
{
uint8_t ret = (uint8_t)((uint32_t)pinst>>12U);
return (IRQn_Type) ret;
}
__STATIC_INLINE bool nrf_drv_is_in_RAM(void const * const ptr)
{
return ((((uintptr_t)ptr) & 0xE0000000u) == 0x20000000u);
}
#endif // SUPPRESS_INLINE_IMPLEMENTATION
#endif // NRF_DRV_COMMON_H__

View File

@ -1,110 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_CONFIG_VALIDATION_H
#define NRF_DRV_CONFIG_VALIDATION_H
#ifdef NRF52
#if (!PERIPHERAL_RESOURCE_SHARING_ENABLED) && \
((SPI0_ENABLED + SPIS0_ENABLED + TWI0_ENABLED + TWIS0_ENABLED) > 1)
#error "Peripherals overlap. SPI0, SPIS0, TWI0, TWIS0 - only one of these can be enabled."
#endif
#if (!PERIPHERAL_RESOURCE_SHARING_ENABLED) && \
((SPI1_ENABLED + SPIS1_ENABLED + TWI1_ENABLED + TWIS1_ENABLED) > 1)
#error "Peripherals overlap. SPI1, SPIS1, TWI1, TWIS1 - only one of these can be enabled."
#endif
#if (!PERIPHERAL_RESOURCE_SHARING_ENABLED) && \
((SPI2_ENABLED + SPIS2_ENABLED) > 1)
#error "Peripherals overlap. SPI2, SPIS2 - only one of these can be enabled."
#endif
#if (!PERIPHERAL_RESOURCE_SHARING_ENABLED) && \
((COMP_ENABLED + LPCOMP_ENABLED) > 1)
#error "COMP and LPCOMP cannot be enabled together. Peripherals overlap."
#endif
#else //NRF51
#if (TWIS0_ENABLED + TWIS1_ENABLED) > 0
#error "TWIS not present in nRF51."
#endif
#if SPIS0_ENABLED > 0
#error "SPIS0 instance not present in nRF51."
#endif
#if (SPI2_ENABLED + SPIS2_ENABLED) > 0
#error "SPI2/SPIS2 instance not present in nRF51."
#endif
#if RTC2_ENABLED
#error "RTC2 not present in NRF51."
#endif
#if (TIMER3_ENABLED + TIMER4_ENABLED) > 0
#error "TIMER3 and TIMER4 not present in nRF51."
#endif
#if (!PERIPHERAL_RESOURCE_SHARING_ENABLED) && \
((SPI0_ENABLED + TWI0_ENABLED) > 1)
#error "Peripherals overlap. SPI0, TWI0 - only one of these can be enabled."
#endif
#if (!PERIPHERAL_RESOURCE_SHARING_ENABLED) && \
((SPI1_ENABLED + SPIS1_ENABLED + TWI1_ENABLED) > 1)
#error "Peripherals overlap. SPI1, SPIS1, TWI1 - only one of these can be enabled."
#endif
#if SAADC_ENABLED > 0
#error "SAADC not present in nRF51."
#endif
#if I2S_ENABLED > 0
#error "I2S not present in nRF51."
#endif
#if COMP_ENABLED > 0
#error "COMP not present in nRF51."
#endif
#endif //NRF51
#endif // NRF_DRV_CONFIG_VALIDATION_H

View File

@ -1,53 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 <stdio.h>
#include "compiler_abstraction.h"
#include "nrf.h"
#include "nrf_delay.h"
/*lint --e{438} "Variable not used" */
void nrf_delay_ms(uint32_t volatile number_of_ms)
{
while(number_of_ms != 0)
{
number_of_ms--;
nrf_delay_us(999);
}
}

View File

@ -1,242 +0,0 @@
#ifndef _NRF_DELAY_H
#define _NRF_DELAY_H
#include "nrf.h"
/**
* @brief Function for delaying execution for number of microseconds.
*
* @note NRF52 has instruction cache and because of that delay is not precise.
*
* @param number_of_ms
*/
/*lint --e{438, 522} "Variable not used" "Function lacks side-effects" */
#if defined ( __CC_ARM )
static __ASM void __INLINE nrf_delay_us(uint32_t volatile number_of_us)
{
loop
SUBS R0, R0, #1
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
#ifdef NRF52
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
#endif
BNE loop
BX LR
}
#elif defined ( __ICCARM__ )
static void __INLINE nrf_delay_us(uint32_t volatile number_of_us)
{
__ASM (
"loop:\n\t"
" SUBS R0, R0, #1\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
#ifdef NRF52
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
" NOP\n\t"
#endif
" BNE.n loop\n\t");
}
#elif defined ( _WIN32 ) || defined ( __unix ) || defined( __APPLE__ )
__STATIC_INLINE void nrf_delay_us(uint32_t volatile number_of_us);
#ifndef CUSTOM_NRF_DELAY_US
__STATIC_INLINE void nrf_delay_us(uint32_t volatile number_of_us)
{}
#endif
#elif defined ( __GNUC__ )
static __INLINE void nrf_delay_us(uint32_t volatile number_of_us) __attribute__((always_inline));
static __INLINE void nrf_delay_us(uint32_t volatile number_of_us)
{
register uint32_t delay __ASM ("r0") = number_of_us;
__ASM volatile (
#if defined(NRF51) && !defined(__ARMCC_VERSION)
".syntax unified\n"
#endif
"1:\n"
" SUBS %0, %0, #1\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
#ifdef NRF52
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
" NOP\n"
#endif
" BNE 1b\n"
#if defined(NRF51) && !defined(__ARMCC_VERSION)
".syntax divided\n"
#endif
: "+r" (delay));
}
#endif
void nrf_delay_ms(uint32_t volatile number_of_ms);
#endif

View File

@ -1,607 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_drv_gpiote.h"
#include "nrf_drv_common.h"
#include "nrf_drv_config.h"
#include "app_util_platform.h"
#include "nrf_assert.h"
#define FORBIDDEN_HANDLER_ADDRESS ((nrf_drv_gpiote_evt_handler_t)UINT32_MAX)
#define PIN_NOT_USED (-1)
#define PIN_USED (-2)
#define NO_CHANNELS (-1)
#define SENSE_FIELD_POS (6)
#define SENSE_FIELD_MASK (0xC0)
/**
* @brief Macro for conveting task-event index to an address of an event register.
*
* Macro utilizes the fact that registers are grouped together in ascending order.
*/
#define TE_IDX_TO_EVENT_ADDR(idx) (nrf_gpiote_events_t)((uint32_t)NRF_GPIOTE_EVENTS_IN_0+(sizeof(uint32_t)*(idx)))
/**
* @brief Macro for conveting task-event index to an address of a task register.
*
* Macro utilizes the fact that registers are grouped together in ascending order.
*/
#define TE_IDX_TO_TASK_ADDR(idx) (nrf_gpiote_tasks_t)((uint32_t)NRF_GPIOTE_TASKS_OUT_0+(sizeof(uint32_t)*(idx)))
//lint -save -e661
typedef struct
{
nrf_drv_gpiote_evt_handler_t handlers[NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
int8_t pin_assignments[NUMBER_OF_PINS];
int8_t port_handlers_pins[GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS];
nrf_drv_state_t state;
} gpiote_control_block_t;
static gpiote_control_block_t m_cb;
__STATIC_INLINE bool pin_in_use(uint32_t pin)
{
return (m_cb.pin_assignments[pin] != PIN_NOT_USED);
}
__STATIC_INLINE bool pin_in_use_as_non_task_out(uint32_t pin)
{
return (m_cb.pin_assignments[pin] == PIN_USED);
}
__STATIC_INLINE bool pin_in_use_by_te(uint32_t pin)
{
return (m_cb.pin_assignments[pin] >= 0 && m_cb.pin_assignments[pin] < NUMBER_OF_GPIO_TE) ? true : false;
}
__STATIC_INLINE bool pin_in_use_by_port(uint32_t pin)
{
return (m_cb.pin_assignments[pin] >= NUMBER_OF_GPIO_TE);
}
__STATIC_INLINE bool pin_in_use_by_gpiote(uint32_t pin)
{
return (m_cb.pin_assignments[pin] >= 0);
}
__STATIC_INLINE void pin_in_use_by_te_set(uint32_t pin,
uint32_t channel_id,
nrf_drv_gpiote_evt_handler_t handler,
bool is_channel)
{
m_cb.pin_assignments[pin] = channel_id;
m_cb.handlers[channel_id] = handler;
if (!is_channel)
{
m_cb.port_handlers_pins[channel_id-NUMBER_OF_GPIO_TE] = (int8_t)pin;
}
}
__STATIC_INLINE void pin_in_use_set(uint32_t pin)
{
m_cb.pin_assignments[pin] = PIN_USED;
}
__STATIC_INLINE void pin_in_use_clear(uint32_t pin)
{
m_cb.pin_assignments[pin] = PIN_NOT_USED;
}
__STATIC_INLINE int8_t channel_port_get(uint32_t pin)
{
return m_cb.pin_assignments[pin];
}
__STATIC_INLINE nrf_drv_gpiote_evt_handler_t channel_handler_get(uint32_t channel)
{
return m_cb.handlers[channel];
}
static int8_t channel_port_alloc(uint32_t pin,nrf_drv_gpiote_evt_handler_t handler, bool channel)
{
int8_t channel_id = NO_CHANNELS;
uint32_t i;
uint32_t start_idx = channel ? 0 : NUMBER_OF_GPIO_TE;
uint32_t end_idx = channel ? NUMBER_OF_GPIO_TE : (NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS);
//critical section
for (i = start_idx; i < end_idx; i++)
{
if (m_cb.handlers[i] == FORBIDDEN_HANDLER_ADDRESS)
{
pin_in_use_by_te_set(pin, i, handler, channel);
channel_id = i;
break;
}
}
//critical section
return channel_id;
}
static void channel_free(uint8_t channel_id)
{
m_cb.handlers[channel_id] = FORBIDDEN_HANDLER_ADDRESS;
if (channel_id >= NUMBER_OF_GPIO_TE)
{
m_cb.port_handlers_pins[channel_id-NUMBER_OF_GPIO_TE] = (int8_t)PIN_NOT_USED;
}
}
ret_code_t nrf_drv_gpiote_init(void)
{
if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED)
{
return NRF_ERROR_INVALID_STATE;
}
uint8_t i;
for (i = 0; i < NUMBER_OF_PINS; i++)
{
pin_in_use_clear(i);
}
for (i = 0; i < (NUMBER_OF_GPIO_TE+GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS); i++)
{
channel_free(i);
}
nrf_drv_common_irq_enable(GPIOTE_IRQn, GPIOTE_CONFIG_IRQ_PRIORITY);
nrf_gpiote_int_enable(GPIOTE_INTENSET_PORT_Msk);
m_cb.state = NRF_DRV_STATE_INITIALIZED;
return NRF_SUCCESS;
}
bool nrf_drv_gpiote_is_init(void)
{
return (m_cb.state != NRF_DRV_STATE_UNINITIALIZED) ? true : false;
}
void nrf_drv_gpiote_uninit(void)
{
ASSERT(m_cb.state!=NRF_DRV_STATE_UNINITIALIZED);
uint32_t i;
for (i = 0; i < NUMBER_OF_PINS; i++)
{
if (pin_in_use_as_non_task_out(i))
{
nrf_drv_gpiote_out_uninit(i);
}
else if( pin_in_use_by_gpiote(i))
{
/* Disable gpiote_in is having the same effect on out pin as gpiote_out_uninit on
* so it can be called on all pins used by GPIOTE.
*/
nrf_drv_gpiote_in_uninit(i);
}
}
m_cb.state = NRF_DRV_STATE_UNINITIALIZED;
}
ret_code_t nrf_drv_gpiote_out_init(nrf_drv_gpiote_pin_t pin,
nrf_drv_gpiote_out_config_t const * p_config)
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(m_cb.state == NRF_DRV_STATE_INITIALIZED);
ASSERT(p_config);
ret_code_t result = NRF_SUCCESS;
if (pin_in_use(pin))
{
result = NRF_ERROR_INVALID_STATE;
}
else
{
if (p_config->task_pin)
{
int8_t channel = channel_port_alloc(pin, NULL, true);
if (channel != NO_CHANNELS)
{
nrf_gpiote_task_configure(channel, pin, p_config->action, p_config->init_state);
}
else
{
result = NRF_ERROR_NO_MEM;
}
}
else
{
pin_in_use_set(pin);
}
if (result == NRF_SUCCESS)
{
if (p_config->init_state == NRF_GPIOTE_INITIAL_VALUE_HIGH)
{
nrf_gpio_pin_set(pin);
}
else
{
nrf_gpio_pin_clear(pin);
}
nrf_gpio_cfg_output(pin);
}
}
return result;
}
void nrf_drv_gpiote_out_uninit(nrf_drv_gpiote_pin_t pin)
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
if (pin_in_use_by_te(pin))
{
channel_free((uint8_t)channel_port_get(pin));
nrf_gpiote_te_default(channel_port_get(pin));
}
pin_in_use_clear(pin);
nrf_gpio_cfg_default(pin);
}
void nrf_drv_gpiote_out_set(nrf_drv_gpiote_pin_t pin)
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(!pin_in_use_by_te(pin))
nrf_gpio_pin_set(pin);
}
void nrf_drv_gpiote_out_clear(nrf_drv_gpiote_pin_t pin)
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(!pin_in_use_by_te(pin))
nrf_gpio_pin_clear(pin);
}
void nrf_drv_gpiote_out_toggle(nrf_drv_gpiote_pin_t pin)
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(!pin_in_use_by_te(pin))
nrf_gpio_pin_toggle(pin);
}
void nrf_drv_gpiote_out_task_enable(nrf_drv_gpiote_pin_t pin)
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use_by_te(pin))
nrf_gpiote_task_enable(m_cb.pin_assignments[pin]);
}
void nrf_drv_gpiote_out_task_disable(nrf_drv_gpiote_pin_t pin)
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use_by_te(pin))
nrf_gpiote_task_disable(m_cb.pin_assignments[pin]);
}
uint32_t nrf_drv_gpiote_out_task_addr_get(nrf_drv_gpiote_pin_t pin)
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use_by_te(pin));
nrf_gpiote_tasks_t task = TE_IDX_TO_TASK_ADDR(channel_port_get(pin));
return nrf_gpiote_task_addr_get(task);
}
void nrf_drv_gpiote_out_task_force(nrf_drv_gpiote_pin_t pin, uint8_t state)
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use_by_te(pin));
nrf_gpiote_outinit_t init_val = state ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW;
nrf_gpiote_task_force(m_cb.pin_assignments[pin], init_val);
}
void nrf_drv_gpiote_out_task_trigger(nrf_drv_gpiote_pin_t pin)
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use(pin));
ASSERT(pin_in_use_by_te(pin));
nrf_gpiote_tasks_t task = TE_IDX_TO_TASK_ADDR(channel_port_get(pin));;
nrf_gpiote_task_set(task);
}
ret_code_t nrf_drv_gpiote_in_init(nrf_drv_gpiote_pin_t pin,
nrf_drv_gpiote_in_config_t const * p_config,
nrf_drv_gpiote_evt_handler_t evt_handler)
{
ASSERT(pin < NUMBER_OF_PINS);
ret_code_t result = NRF_SUCCESS;
/* Only one GPIOTE channel can be assigned to one physical pin. */
if (pin_in_use_by_gpiote(pin))
{
result = NRF_ERROR_INVALID_STATE;
}
else
{
int8_t channel = channel_port_alloc(pin, evt_handler, p_config->hi_accuracy);
if (channel != NO_CHANNELS)
{
if (p_config->is_watcher)
{
nrf_gpio_cfg_watcher(pin);
}
else
{
nrf_gpio_cfg_input(pin,p_config->pull);
}
if (p_config->hi_accuracy)
{
nrf_gpiote_event_configure(channel, pin,p_config->sense);
}
else
{
m_cb.port_handlers_pins[channel-NUMBER_OF_GPIO_TE] |= (p_config->sense)<< SENSE_FIELD_POS;
}
}
else
{
result = NRF_ERROR_NO_MEM;
}
}
return result;
}
void nrf_drv_gpiote_in_event_enable(nrf_drv_gpiote_pin_t pin, bool int_enable)
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use_by_gpiote(pin));
if (pin_in_use_by_port(pin))
{
uint8_t pin_and_sense = m_cb.port_handlers_pins[channel_port_get(pin)-NUMBER_OF_GPIO_TE];
nrf_gpiote_polarity_t polarity = (nrf_gpiote_polarity_t)(pin_and_sense >> SENSE_FIELD_POS);
nrf_gpio_pin_sense_t sense;
if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
{
/* read current pin state and set for next sense to oposit */
sense = (nrf_gpio_pins_read() & (1 << pin)) ?
NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
}
else
{
sense = (polarity == NRF_GPIOTE_POLARITY_LOTOHI) ?
NRF_GPIO_PIN_SENSE_HIGH : NRF_GPIO_PIN_SENSE_LOW;
}
nrf_gpio_cfg_sense_set(pin,sense);
}
else if(pin_in_use_by_te(pin))
{
int32_t channel = (int32_t)channel_port_get(pin);
nrf_gpiote_events_t event = TE_IDX_TO_EVENT_ADDR(channel);
nrf_gpiote_event_enable(channel);
nrf_gpiote_event_clear(event);
if (int_enable)
{
nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(channel_port_get(pin));
// Enable the interrupt only if event handler was provided.
if (handler)
{
nrf_gpiote_int_enable(1 << channel);
}
}
}
}
void nrf_drv_gpiote_in_event_disable(nrf_drv_gpiote_pin_t pin)
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use_by_gpiote(pin));
if (pin_in_use_by_port(pin))
{
nrf_gpio_cfg_sense_set(pin,NRF_GPIO_PIN_NOSENSE);
}
else if(pin_in_use_by_te(pin))
{
int32_t channel = (int32_t)channel_port_get(pin);
nrf_gpiote_event_disable(channel);
nrf_gpiote_int_disable(1 << channel);
}
}
void nrf_drv_gpiote_in_uninit(nrf_drv_gpiote_pin_t pin)
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use_by_gpiote(pin));
nrf_drv_gpiote_in_event_disable(pin);
if(pin_in_use_by_te(pin))
{
nrf_gpiote_te_default(channel_port_get(pin));
}
nrf_gpio_cfg_default(pin);
channel_free((uint8_t)channel_port_get(pin));
pin_in_use_clear(pin);
}
bool nrf_drv_gpiote_in_is_set(nrf_drv_gpiote_pin_t pin)
{
ASSERT(pin < NUMBER_OF_PINS);
return nrf_gpio_pin_read(pin) ? true : false;
}
uint32_t nrf_drv_gpiote_in_event_addr_get(nrf_drv_gpiote_pin_t pin)
{
ASSERT(pin < NUMBER_OF_PINS);
ASSERT(pin_in_use_by_te(pin));
nrf_gpiote_events_t event = TE_IDX_TO_EVENT_ADDR(channel_port_get(pin));
return nrf_gpiote_event_addr_get(event);
}
void GPIOTE_IRQHandler(void)
{
uint32_t status = 0;
uint32_t input = 0;
/* collect status of all GPIOTE pin events. Processing is done once all are collected and cleared.*/
uint32_t i;
nrf_gpiote_events_t event = NRF_GPIOTE_EVENTS_IN_0;
uint32_t mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;
for (i = 0; i < NUMBER_OF_GPIO_TE; i++)
{
if (nrf_gpiote_event_is_set(event) && nrf_gpiote_int_is_enabled(mask))
{
nrf_gpiote_event_clear(event);
status |= mask;
}
mask <<= 1;
/* Incrementing to next event, utilizing the fact that events are grouped together
* in ascending order. */
event = (nrf_gpiote_events_t)((uint32_t)event + sizeof(uint32_t));
}
/* collect PORT status event, if event is set read pins state. Processing is postponed to the
* end of interrupt. */
if (nrf_gpiote_event_is_set(NRF_GPIOTE_EVENTS_PORT))
{
nrf_gpiote_event_clear(NRF_GPIOTE_EVENTS_PORT);
status |= (uint32_t)NRF_GPIOTE_INT_PORT_MASK;
input = nrf_gpio_pins_read();
}
/* Process pin events. */
if (status & NRF_GPIOTE_INT_IN_MASK)
{
mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;
for (i = 0; i < NUMBER_OF_GPIO_TE; i++)
{
if (mask & status)
{
nrf_drv_gpiote_pin_t pin = nrf_gpiote_event_pin_get(i);
nrf_gpiote_polarity_t polarity = nrf_gpiote_event_polarity_get(i);
nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(i);
handler(pin,polarity);
}
mask <<= 1;
}
}
if (status & (uint32_t)NRF_GPIOTE_INT_PORT_MASK)
{
/* Process port event. */
uint8_t repeat = 0;
uint32_t toggle_mask = 0;
uint32_t pins_to_check = 0xFFFFFFFFuL;
do
{
repeat = 0;
for (i = 0; i < GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS; i++)
{
uint8_t pin_and_sense = m_cb.port_handlers_pins[i];
nrf_drv_gpiote_pin_t pin = (pin_and_sense & ~SENSE_FIELD_MASK);
if ((m_cb.port_handlers_pins[i] != PIN_NOT_USED)
&& ((1UL << pin) & pins_to_check))
{
nrf_gpiote_polarity_t polarity =
(nrf_gpiote_polarity_t)((pin_and_sense & SENSE_FIELD_MASK) >> SENSE_FIELD_POS);
nrf_drv_gpiote_evt_handler_t handler = channel_handler_get(channel_port_get(pin));
if (handler || polarity == NRF_GPIOTE_POLARITY_TOGGLE)
{
mask = 1 << pin;
if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
{
toggle_mask |= mask;
}
nrf_gpio_pin_sense_t sense = nrf_gpio_pin_sense_get(pin);
if (((mask & input) && (sense==NRF_GPIO_PIN_SENSE_HIGH)) ||
(!(mask & input) && (sense==NRF_GPIO_PIN_SENSE_LOW)) )
{
if (polarity == NRF_GPIOTE_POLARITY_TOGGLE)
{
nrf_gpio_pin_sense_t next_sense = (sense == NRF_GPIO_PIN_SENSE_HIGH) ?
NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
nrf_gpio_cfg_sense_set(pin, next_sense);
++repeat;
}
if (handler)
{
handler(pin, polarity);
}
}
}
}
}
if (repeat)
{
// When one of the pins in low-accuracy and toggle mode becomes active,
// it's sense mode is inverted to clear the internal SENSE signal.
// State of any other enabled low-accuracy input in toggle mode must be checked
// explicitly, because it does not trigger the interrput when SENSE signal is active.
// For more information about SENSE functionality, refer to Product Specification.
uint32_t new_input = nrf_gpio_pins_read();
if (new_input == input)
{
//No change.
repeat = 0;
}
else
{
input = new_input;
pins_to_check = toggle_mask;
}
}
}
while (repeat);
}
}
//lint -restore

View File

@ -1,336 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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__
#define NRF_DRV_GPIOTE__
/**
* @addtogroup nrf_gpiote GPIOTE abstraction and driver
* @ingroup nrf_drivers
* @brief GPIOTE APIs.
* @defgroup nrf_drv_gpiote GPIOTE driver
* @{
* @ingroup nrf_gpiote
* @brief GPIOTE driver for managing input and output pins.
*/
#include "nrf_gpiote.h"
#include "nrf_gpio.h"
#include "nrf_drv_config.h"
#include "sdk_errors.h"
#include <stdint.h>
#include <stdbool.h>
/**@brief Input pin configuration. */
typedef struct
{
nrf_gpiote_polarity_t sense; /**< Transition that triggers interrupt. */
nrf_gpio_pin_pull_t pull; /**< Pulling mode. */
bool is_watcher; /**< True when the input pin is tracking an output pin. */
bool hi_accuracy;/**< True when high accuracy (IN_EVENT) is used. */
} nrf_drv_gpiote_in_config_t;
/**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect low-to-high transition.
* @details Set hi_accu to true to use IN_EVENT. */
#define GPIOTE_CONFIG_IN_SENSE_LOTOHI(hi_accu) \
{ \
.is_watcher = false, \
.hi_accuracy = hi_accu, \
.pull = NRF_GPIO_PIN_NOPULL, \
.sense = NRF_GPIOTE_POLARITY_LOTOHI, \
}
/**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect high-to-low transition.
* @details Set hi_accu to true to use IN_EVENT. */
#define GPIOTE_CONFIG_IN_SENSE_HITOLO(hi_accu) \
{ \
.is_watcher = false, \
.hi_accuracy = hi_accu, \
.pull = NRF_GPIO_PIN_NOPULL, \
.sense = NRF_GPIOTE_POLARITY_HITOLO, \
}
/**@brief Macro for configuring a pin to use a GPIO IN or PORT EVENT to detect any change on the pin.
* @details Set hi_accu to true to use IN_EVENT.*/
#define GPIOTE_CONFIG_IN_SENSE_TOGGLE(hi_accu) \
{ \
.is_watcher = false, \
.hi_accuracy = hi_accu, \
.pull = NRF_GPIO_PIN_NOPULL, \
.sense = NRF_GPIOTE_POLARITY_TOGGLE, \
}
/**@brief Output pin configuration. */
typedef struct
{
nrf_gpiote_polarity_t action; /**< Configuration of the pin task. */
nrf_gpiote_outinit_t init_state; /**< Initial state of the output pin. */
bool task_pin; /**< True if the pin is controlled by a GPIOTE task. */
} nrf_drv_gpiote_out_config_t;
/**@brief Macro for configuring a pin to use as output. GPIOTE is not used for the pin. */
#define GPIOTE_CONFIG_OUT_SIMPLE(init_high) \
{ \
.init_state = init_high ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW, \
.task_pin = false, \
}
/**@brief Macro for configuring a pin to use the GPIO OUT TASK to change the state from high to low.
* @details The task will clear the pin. Therefore, the pin is set initially. */
#define GPIOTE_CONFIG_OUT_TASK_LOW \
{ \
.init_state = NRF_GPIOTE_INITIAL_VALUE_HIGH, \
.task_pin = true, \
.action = NRF_GPIOTE_POLARITY_HITOLO, \
}
/**@brief Macro for configuring a pin to use the GPIO OUT TASK to change the state from low to high.
* @details The task will set the pin. Therefore, the pin is cleared initially. */
#define GPIOTE_CONFIG_OUT_TASK_HIGH \
{ \
.init_state = NRF_GPIOTE_INITIAL_VALUE_LOW, \
.task_pin = true, \
.action = NRF_GPIOTE_POLARITY_LOTOHI, \
}
/**@brief Macro for configuring a pin to use the GPIO OUT TASK to toggle the pin state.
* @details The initial pin state must be provided. */
#define GPIOTE_CONFIG_OUT_TASK_TOGGLE(init_high) \
{ \
.init_state = init_high ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW, \
.task_pin = true, \
.action = NRF_GPIOTE_POLARITY_TOGGLE, \
}
/** @brief Pin. */
typedef uint32_t nrf_drv_gpiote_pin_t;
/**
* @brief Pin event handler prototype.
* @param pin Pin that triggered this event.
* @param action Action that lead to triggering this event.
*/
typedef void (*nrf_drv_gpiote_evt_handler_t)(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action);
/**
* @brief Function for initializing the GPIOTE module.
*
* @details Only static configuration is supported to prevent the shared
* resource being customized by the initiator.
*
* @retval NRF_SUCCESS If initialization was successful.
* @retval NRF_ERROR_INVALID_STATE If the driver was already initialized.
*/
ret_code_t nrf_drv_gpiote_init(void);
/**
* @brief Function for checking if the GPIOTE module is initialized.
*
* @details The GPIOTE module is a shared module. Therefore, you should check if
* the module is already initialized and skip initialization if it is.
*
* @retval true If the module is already initialized.
* @retval false If the module is not initialized.
*/
bool nrf_drv_gpiote_is_init(void);
/**
* @brief Function for uninitializing the GPIOTE module.
*/
void nrf_drv_gpiote_uninit(void);
/**
* @brief Function for initializing a GPIOTE output pin.
* @details The output pin can be controlled by the CPU or by PPI. The initial
* configuration specifies which mode is used. If PPI mode is used, the driver
* attempts to allocate one of the available GPIOTE channels. If no channel is
* available, an error is returned.
*
* @param[in] pin Pin.
* @param[in] p_config Initial configuration.
*
* @retval NRF_SUCCESS If initialization was successful.
* @retval NRF_ERROR_INVALID_STATE If the driver is not initialized or the pin is already used.
* @retval NRF_ERROR_NO_MEM If no GPIOTE channel is available.
*/
ret_code_t nrf_drv_gpiote_out_init(nrf_drv_gpiote_pin_t pin,
nrf_drv_gpiote_out_config_t const * p_config);
/**
* @brief Function for uninitializing a GPIOTE output pin.
* @details The driver frees the GPIOTE channel if the output pin was using one.
*
* @param[in] pin Pin.
*/
void nrf_drv_gpiote_out_uninit(nrf_drv_gpiote_pin_t pin);
/**
* @brief Function for setting a GPIOTE output pin.
*
* @param[in] pin Pin.
*/
void nrf_drv_gpiote_out_set(nrf_drv_gpiote_pin_t pin);
/**
* @brief Function for clearing a GPIOTE output pin.
*
* @param[in] pin Pin.
*/
void nrf_drv_gpiote_out_clear(nrf_drv_gpiote_pin_t pin);
/**
* @brief Function for toggling a GPIOTE output pin.
*
* @param[in] pin Pin.
*/
void nrf_drv_gpiote_out_toggle(nrf_drv_gpiote_pin_t pin);
/**
* @brief Function for enabling a GPIOTE output pin task.
*
* @param[in] pin Pin.
*/
void nrf_drv_gpiote_out_task_enable(nrf_drv_gpiote_pin_t pin);
/**
* @brief Function for disabling a GPIOTE output pin task.
*
* @param[in] pin Pin.
*/
void nrf_drv_gpiote_out_task_disable(nrf_drv_gpiote_pin_t pin);
/**
* @brief Function for getting the address of a configurable GPIOTE task.
*
* @param[in] pin Pin.
*/
uint32_t nrf_drv_gpiote_out_task_addr_get(nrf_drv_gpiote_pin_t pin);
/**
* @brief Function for initializing a GPIOTE input pin.
* @details The input pin can act in two ways:
* - lower accuracy but low power (high frequency clock not needed)
* - higher accuracy (high frequency clock required)
*
* The initial configuration specifies which mode is used.
* If high-accuracy mode is used, the driver attempts to allocate one
* of the available GPIOTE channels. If no channel is
* available, an error is returned.
* In low accuracy mode SENSE feature is used. In this case only one active pin
* can be detected at a time. It can be worked around by setting all of the used
* low accuracy pins to toggle mode.
* For more information about SENSE functionality, refer to Product Specification.
*
* @param[in] pin Pin.
* @param[in] p_config Initial configuration.
* @param[in] evt_handler User function to be called when the configured transition occurs.
*
* @retval NRF_SUCCESS If initialization was successful.
* @retval NRF_ERROR_INVALID_STATE If the driver is not initialized or the pin is already used.
* @retval NRF_ERROR_NO_MEM If no GPIOTE channel is available.
*/
ret_code_t nrf_drv_gpiote_in_init(nrf_drv_gpiote_pin_t pin,
nrf_drv_gpiote_in_config_t const * p_config,
nrf_drv_gpiote_evt_handler_t evt_handler);
/**
* @brief Function for uninitializing a GPIOTE input pin.
* @details The driver frees the GPIOTE channel if the input pin was using one.
*
* @param[in] pin Pin.
*/
void nrf_drv_gpiote_in_uninit(nrf_drv_gpiote_pin_t pin);
/**
* @brief Function for enabling sensing of a GPIOTE input pin.
*
* @details If the input pin is configured as high-accuracy pin, the function
* enables an IN_EVENT. Otherwise, the function enables the GPIO sense mechanism.
* Note that a PORT event is shared between multiple pins, therefore the
* interrupt is always enabled.
*
* @param[in] pin Pin.
* @param[in] int_enable True to enable the interrupt. Always valid for a high-accuracy pin.
*/
void nrf_drv_gpiote_in_event_enable(nrf_drv_gpiote_pin_t pin, bool int_enable);
/**
* @brief Function for disabling a GPIOTE input pin.
*
* @param[in] pin Pin.
*/
void nrf_drv_gpiote_in_event_disable(nrf_drv_gpiote_pin_t pin);
/**
* @brief Function for checking if a GPIOTE input pin is set.
*
* @param[in] pin Pin.
* @retval true If the input pin is set.
* @retval false If the input pin is not set.
*/
bool nrf_drv_gpiote_in_is_set(nrf_drv_gpiote_pin_t pin);
/**
* @brief Function for getting the address of a GPIOTE input pin event.
* @details If the pin is configured to use low-accuracy mode, the address of the PORT event is returned.
*
* @param[in] pin Pin.
*/
uint32_t nrf_drv_gpiote_in_event_addr_get(nrf_drv_gpiote_pin_t pin);
/**
* @brief Function for forcing a specific state on the pin configured as task.
*
* @param[in] pin Pin.
* @param[in] state Pin state.
*/
void nrf_drv_gpiote_out_task_force(nrf_drv_gpiote_pin_t pin, uint8_t state);
/**
* @brief Function for triggering the task manually.
*
* @param[in] pin Pin.
*/
void nrf_drv_gpiote_out_task_trigger(nrf_drv_gpiote_pin_t pin);
/**
*@}
**/
#endif //NRF_DRV_GPIOTE__

View File

@ -1,105 +0,0 @@
/*
* Copyright (c) 2014 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 ADC HAL implementation
*/
#include "nrf_adc.h"
#ifndef NRF52
/**
* @brief Function for configuring ADC.
*
* This function powers on ADC and configures it. ADC is in DISABLE state after configuration,
* so it should be enabled before using it.
*
* @param[in] config Requested configuration.
*/
void nrf_adc_configure(nrf_adc_config_t * config)
{
uint32_t config_reg = 0;
config_reg |= ((uint32_t)config->resolution << ADC_CONFIG_RES_Pos) & ADC_CONFIG_RES_Msk;
config_reg |= ((uint32_t)config->scaling << ADC_CONFIG_INPSEL_Pos) & ADC_CONFIG_INPSEL_Msk;
config_reg |= ((uint32_t)config->reference << ADC_CONFIG_REFSEL_Pos) & ADC_CONFIG_REFSEL_Msk;
if (config->reference & ADC_CONFIG_EXTREFSEL_Msk)
{
config_reg |= config->reference & ADC_CONFIG_EXTREFSEL_Msk;
}
/* select input */
nrf_adc_input_select(NRF_ADC_CONFIG_INPUT_DISABLED);
/* set new configuration keeping selected input */
NRF_ADC->CONFIG = config_reg | (NRF_ADC->CONFIG & ADC_CONFIG_PSEL_Msk);
}
/**
* @brief Blocking function for executing single ADC conversion.
*
* This function selects the desired input, starts a single conversion,
* waits for it to finish, and returns the result.
* ADC is left in STOP state, the given input is selected.
* This function does not check if ADC is initialized and powered.
*
* @param[in] input Requested input to be selected.
*
* @return Conversion result
*/
int32_t nrf_adc_convert_single(nrf_adc_config_input_t input)
{
int32_t val;
nrf_adc_input_select(input);
nrf_adc_start();
while (!nrf_adc_conversion_finished())
{
}
nrf_adc_conversion_event_clean();
val = nrf_adc_result_get();
nrf_adc_stop();
return val;
}
#endif

View File

@ -1,443 +0,0 @@
/*
* Copyright (c) 2014 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_ADC_H_
#define NRF_ADC_H_
/**
* @defgroup nrf_adc_hal ADC HAL
* @{
* @ingroup nrf_adc
* @brief @tagAPI51 Hardware access layer for managing the analog-to-digital converter (ADC).
*/
#include <stdbool.h>
#include <stddef.h>
#include "nrf.h"
#ifndef NRF52
/**
* @enum nrf_adc_config_resolution_t
* @brief Resolution of the analog-to-digital converter.
*/
/**
* @brief ADC interrupts.
*/
typedef enum
{
NRF_ADC_INT_END_MASK = ADC_INTENSET_END_Msk, /**< ADC interrupt on END event. */
} nrf_adc_int_mask_t;
typedef enum
{
NRF_ADC_CONFIG_RES_8BIT = ADC_CONFIG_RES_8bit, /**< 8 bit resolution. */
NRF_ADC_CONFIG_RES_9BIT = ADC_CONFIG_RES_9bit, /**< 9 bit resolution. */
NRF_ADC_CONFIG_RES_10BIT = ADC_CONFIG_RES_10bit, /**< 10 bit resolution. */
} nrf_adc_config_resolution_t;
/**
* @enum nrf_adc_config_scaling_t
* @brief Scaling factor of the analog-to-digital conversion.
*/
typedef enum
{
NRF_ADC_CONFIG_SCALING_INPUT_FULL_SCALE = ADC_CONFIG_INPSEL_AnalogInputNoPrescaling, /**< Full scale input. */
NRF_ADC_CONFIG_SCALING_INPUT_TWO_THIRDS = ADC_CONFIG_INPSEL_AnalogInputTwoThirdsPrescaling, /**< 2/3 scale input. */
NRF_ADC_CONFIG_SCALING_INPUT_ONE_THIRD = ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling, /**< 1/3 scale input. */
NRF_ADC_CONFIG_SCALING_SUPPLY_TWO_THIRDS = ADC_CONFIG_INPSEL_SupplyTwoThirdsPrescaling, /**< 2/3 of supply. */
NRF_ADC_CONFIG_SCALING_SUPPLY_ONE_THIRD = ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling /**< 1/3 of supply. */
} nrf_adc_config_scaling_t;
/**
* @enum nrf_adc_config_reference_t
* @brief Reference selection of the analog-to-digital converter.
*/
typedef enum
{
NRF_ADC_CONFIG_REF_VBG = ADC_CONFIG_REFSEL_VBG, /**< 1.2 V reference. */
NRF_ADC_CONFIG_REF_SUPPLY_ONE_HALF = ADC_CONFIG_REFSEL_SupplyOneHalfPrescaling, /**< 1/2 of power supply. */
NRF_ADC_CONFIG_REF_SUPPLY_ONE_THIRD = ADC_CONFIG_REFSEL_SupplyOneThirdPrescaling, /**< 1/3 of power supply. */
NRF_ADC_CONFIG_REF_EXT_REF0 = ADC_CONFIG_REFSEL_External |
ADC_CONFIG_EXTREFSEL_AnalogReference0 <<
ADC_CONFIG_EXTREFSEL_Pos, /**< External reference 0. */
NRF_ADC_CONFIG_REF_EXT_REF1 = ADC_CONFIG_REFSEL_External |
ADC_CONFIG_EXTREFSEL_AnalogReference1 << ADC_CONFIG_EXTREFSEL_Pos, /**< External reference 0. */
} nrf_adc_config_reference_t;
/**
* @enum nrf_adc_config_input_t
* @brief Input selection of the analog-to-digital converter.
*/
typedef enum
{
NRF_ADC_CONFIG_INPUT_DISABLED = ADC_CONFIG_PSEL_Disabled, /**< No input selected. */
NRF_ADC_CONFIG_INPUT_0 = ADC_CONFIG_PSEL_AnalogInput0, /**< Input 0. */
NRF_ADC_CONFIG_INPUT_1 = ADC_CONFIG_PSEL_AnalogInput1, /**< Input 1. */
NRF_ADC_CONFIG_INPUT_2 = ADC_CONFIG_PSEL_AnalogInput2, /**< Input 2. */
NRF_ADC_CONFIG_INPUT_3 = ADC_CONFIG_PSEL_AnalogInput3, /**< Input 3. */
NRF_ADC_CONFIG_INPUT_4 = ADC_CONFIG_PSEL_AnalogInput4, /**< Input 4. */
NRF_ADC_CONFIG_INPUT_5 = ADC_CONFIG_PSEL_AnalogInput5, /**< Input 5. */
NRF_ADC_CONFIG_INPUT_6 = ADC_CONFIG_PSEL_AnalogInput6, /**< Input 6. */
NRF_ADC_CONFIG_INPUT_7 = ADC_CONFIG_PSEL_AnalogInput7, /**< Input 7. */
} nrf_adc_config_input_t;
/**
* @enum nrf_adc_task_t
* @brief Analog-to-digital converter tasks.
*/
typedef enum
{
/*lint -save -e30*/
NRF_ADC_TASK_START = offsetof(NRF_ADC_Type, TASKS_START), /**< ADC start sampling task. */
NRF_ADC_TASK_STOP = offsetof(NRF_ADC_Type, TASKS_STOP) /**< ADC stop sampling task. */
/*lint -restore*/
} nrf_adc_task_t;
/**
* @enum nrf_adc_event_t
* @brief Analog-to-digital converter events.
*/
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
{
/*lint -save -e30*/
NRF_ADC_EVENT_END = offsetof(NRF_ADC_Type, EVENTS_END) /**< End of conversion event. */
/*lint -restore*/
} nrf_adc_event_t;
/**@brief Analog-to-digital converter configuration. */
typedef struct
{
nrf_adc_config_resolution_t resolution; /**< ADC resolution. */
nrf_adc_config_scaling_t scaling; /**< ADC scaling factor. */
nrf_adc_config_reference_t reference; /**< ADC reference. */
} nrf_adc_config_t;
/** Default ADC configuration. */
#define NRF_ADC_CONFIG_DEFAULT { NRF_ADC_CONFIG_RES_10BIT, \
NRF_ADC_CONFIG_SCALING_INPUT_ONE_THIRD, \
NRF_ADC_CONFIG_REF_VBG }
/**
* @brief Function for configuring ADC.
*
* This function powers on the analog-to-digital converter and configures it.
* After the configuration, the ADC is in DISABLE state and must be
* enabled before using it.
*
* @param[in] config Configuration parameters.
*/
void nrf_adc_configure(nrf_adc_config_t * config);
/**
* @brief Blocking function for executing a single ADC conversion.
*
* This function selects the desired input, starts a single conversion,
* waits for it to finish, and returns the result.
* After the input is selected, the analog-to-digital converter
* is left in STOP state.
* The function does not check if the ADC is initialized and powered.
*
* @param[in] input Input to be selected.
*
* @return Conversion result.
*/
int32_t nrf_adc_convert_single(nrf_adc_config_input_t input);
/**
* @brief Function for selecting ADC input.
*
* This function selects the active input of ADC. Ensure that
* the ADC is powered on and in IDLE state before calling this function.
*
* @param[in] input Input to be selected.
*/
__STATIC_INLINE void nrf_adc_input_select(nrf_adc_config_input_t input)
{
NRF_ADC->CONFIG =
((uint32_t)input << ADC_CONFIG_PSEL_Pos) | (NRF_ADC->CONFIG & ~ADC_CONFIG_PSEL_Msk);
if (input != NRF_ADC_CONFIG_INPUT_DISABLED)
{
NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled << ADC_ENABLE_ENABLE_Pos;
}
else
{
NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Disabled << ADC_ENABLE_ENABLE_Pos;
}
}
/**
* @brief Function for retrieving the ADC conversion result.
*
* This function retrieves and returns the last analog-to-digital conversion result.
*
* @return Last conversion result.
*/
__STATIC_INLINE int32_t nrf_adc_result_get(void)
{
return (int32_t)NRF_ADC->RESULT;
}
/**
* @brief Function for checking whether the ADC is busy.
*
* This function checks whether the analog-to-digital converter is busy with a conversion.
*
* @retval true If the ADC is busy.
* @retval false If the ADC is not busy.
*/
__STATIC_INLINE bool nrf_adc_is_busy(void)
{
return ( (NRF_ADC->BUSY & ADC_BUSY_BUSY_Msk) == ADC_BUSY_BUSY_Msk);
}
/**
* @brief Function for getting the ADC's enabled interrupts.
*
* @param[in] mask Mask of interrupts to check.
*
* @return State of the interrupts selected by the mask.
*
* @sa nrf_adc_int_enable()
* @sa nrf_adc_int_disable()
*/
__STATIC_INLINE uint32_t nrf_adc_int_get(uint32_t mask)
{
return (NRF_ADC->INTENSET & mask); // when read this register will return the value of INTEN.
}
/**
* @brief Function for starting conversion.
*
* @sa nrf_adc_stop()
*
*/
__STATIC_INLINE void nrf_adc_start(void)
{
NRF_ADC->TASKS_START = 1;
}
/**
* @brief Function for stopping conversion.
*
* If the analog-to-digital converter is in inactive state, power consumption is reduced.
*
* @sa nrf_adc_start()
*
*/
__STATIC_INLINE void nrf_adc_stop(void)
{
NRF_ADC->TASKS_STOP = 1;
}
/**
* @brief Function for checking if the requested ADC conversion has ended.
*
* @retval true If the task has finished.
* @retval false If the task is still running.
*/
__STATIC_INLINE bool nrf_adc_conversion_finished(void)
{
return ((bool)NRF_ADC->EVENTS_END);
}
/**
* @brief Function for clearing the conversion END event.
*/
__STATIC_INLINE void nrf_adc_conversion_event_clean(void)
{
NRF_ADC->EVENTS_END = 0;
}
/**
* @brief Function for getting the address of an ADC task register.
*
* @param[in] adc_task ADC task.
*
* @return Address of the specified ADC task.
*/
__STATIC_INLINE uint32_t nrf_adc_task_address_get(nrf_adc_task_t adc_task);
/**
* @brief Function for getting the address of a specific ADC event register.
*
* @param[in] adc_event ADC event.
*
* @return Address of the specified ADC event.
*/
__STATIC_INLINE uint32_t nrf_adc_event_address_get(nrf_adc_event_t adc_event);
/**
* @brief Function for setting the CONFIG register in ADC.
*
* @param[in] configuration Value to be written to the CONFIG register.
*/
__STATIC_INLINE void nrf_adc_config_set(uint32_t configuration);
/**
* @brief Function for clearing an ADC event.
*
* @param[in] event Event to clear.
*/
__STATIC_INLINE void nrf_adc_event_clear(nrf_adc_event_t event);
/**
* @brief Function for checking state of an ADC event.
*
* @param[in] event Event to check.
*
* @retval true If the event is set.
* @retval false If the event is not set.
*/
__STATIC_INLINE bool nrf_adc_event_check(nrf_adc_event_t event);
/**
* @brief Function for enabling specified interrupts.
*
* @param[in] int_mask Interrupts to enable.
*/
__STATIC_INLINE void nrf_adc_int_enable(uint32_t int_mask);
/**
* @brief Function for disabling specified interrupts.
*
* @param[in] int_mask Interrupts to disable.
*/
__STATIC_INLINE void nrf_adc_int_disable(uint32_t int_mask);
/**
* @brief Function for retrieving the state of a given interrupt.
*
* @param[in] int_mask Interrupt to check.
*
* @retval true If the interrupt is enabled.
* @retval false If the interrupt is not enabled.
*/
__STATIC_INLINE bool nrf_adc_int_enable_check(nrf_adc_int_mask_t int_mask);
/**
* @brief Function for activating a specific ADC task.
*
* @param[in] task Task to activate.
*/
__STATIC_INLINE void nrf_adc_task_trigger(nrf_adc_task_t task);
/**
* @brief Function for enabling ADC.
*
*/
__STATIC_INLINE void nrf_adc_enable(void);
/**
* @brief Function for disabling ADC.
*
*/
__STATIC_INLINE void nrf_adc_disable(void);
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE uint32_t nrf_adc_task_address_get(nrf_adc_task_t adc_task)
{
return (uint32_t)((uint8_t *)NRF_ADC + adc_task);
}
__STATIC_INLINE uint32_t nrf_adc_event_address_get(nrf_adc_event_t adc_event)
{
return (uint32_t)((uint8_t *)NRF_ADC + adc_event);
}
__STATIC_INLINE void nrf_adc_config_set(uint32_t configuration)
{
NRF_ADC->CONFIG = configuration;
}
__STATIC_INLINE void nrf_adc_event_clear(nrf_adc_event_t event)
{
*((volatile uint32_t *)((uint8_t *)NRF_ADC + (uint32_t)event)) = 0x0UL;
}
__STATIC_INLINE bool nrf_adc_event_check(nrf_adc_event_t event)
{
return (bool)*(volatile uint32_t *)((uint8_t *)NRF_ADC + (uint32_t)event);
}
__STATIC_INLINE void nrf_adc_int_enable(uint32_t int_mask)
{
NRF_ADC->INTENSET = int_mask;
}
__STATIC_INLINE void nrf_adc_int_disable(uint32_t int_mask)
{
NRF_ADC->INTENCLR = int_mask;
}
__STATIC_INLINE bool nrf_adc_int_enable_check(nrf_adc_int_mask_t int_mask)
{
return (bool)(NRF_ADC->INTENSET & int_mask);
}
__STATIC_INLINE void nrf_adc_task_trigger(nrf_adc_task_t task)
{
*((volatile uint32_t *)((uint8_t *)NRF_ADC + (uint32_t)task)) = 0x1UL;
}
__STATIC_INLINE void nrf_adc_enable(void)
{
NRF_ADC->ENABLE = 1;
}
__STATIC_INLINE void nrf_adc_disable(void)
{
NRF_ADC->ENABLE = 0;
}
#endif
#endif /* NRF52 */
/**
*@}
**/
#endif /* NRF_ADC_H_ */

View File

@ -1,441 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_CLOCK_H__
#define NRF_CLOCK_H__
#include <stddef.h>
#include <stdbool.h>
#include "nrf.h"
/**
* @defgroup nrf_clock_hal Clock HAL
* @{
* @ingroup nrf_clock
* @brief Hardware access layer for managing the low-frequency clock (LFCLK) and the high-frequency clock (HFCLK).
*/
#define NRF_CLOCK_TASK_TRIGGER (1UL)
#define NRF_CLOCK_EVENT_CLEAR (0UL)
/**
* @brief Low-frequency clock sources.
* @details Used by LFCLKSRC, LFCLKSTAT, and LFCLKSRCCOPY registers.
*/
typedef enum
{
NRF_CLOCK_LFCLK_RC = CLOCK_LFCLKSRC_SRC_RC, /**< Internal 32 kHz RC oscillator. */
NRF_CLOCK_LFCLK_Xtal = CLOCK_LFCLKSRC_SRC_Xtal, /**< External 32 kHz crystal. */
NRF_CLOCK_LFCLK_Synth = CLOCK_LFCLKSRC_SRC_Synth /**< Internal 32 kHz synthesizer from HFCLK system clock. */
} nrf_clock_lfclk_t;
/**
* @brief High-frequency clock sources.
*/
typedef enum
{
NRF_CLOCK_HFCLK_LOW_ACCURACY = CLOCK_HFCLKSTAT_SRC_RC, /**< Internal 16 MHz RC oscillator. */
NRF_CLOCK_HFCLK_HIGH_ACCURACY = CLOCK_HFCLKSTAT_SRC_Xtal /**< External 16 MHz/32 MHz crystal oscillator. */
} nrf_clock_hfclk_t;
/**
* @brief Trigger status of task LFCLKSTART/HFCLKSTART.
* @details Used by LFCLKRUN and HFCLKRUN registers.
*/
typedef enum
{
NRF_CLOCK_START_TASK_NOT_TRIGGERED = CLOCK_LFCLKRUN_STATUS_NotTriggered, /**< Task LFCLKSTART/HFCLKSTART has not been triggered. */
NRF_CLOCK_START_TASK_TRIGGERED = CLOCK_LFCLKRUN_STATUS_Triggered /**< Task LFCLKSTART/HFCLKSTART has been triggered. */
} nrf_clock_start_task_status_t;
/**
* @brief Crystal frequency selection.
*/
typedef enum
{
#ifdef NRF51
NRF_CLOCK_XTALFREQ_Default = CLOCK_XTALFREQ_XTALFREQ_16MHz, /**< Default. 32 MHz. */
NRF_CLOCK_XTALFREQ_16MHz = CLOCK_XTALFREQ_XTALFREQ_16MHz, /**< 16 MHz crystal. */
NRF_CLOCK_XTALFREQ_32MHz = CLOCK_XTALFREQ_XTALFREQ_32MHz /**< 32 MHz crystal. */
#elif defined NRF52
NRF_CLOCK_XTALFREQ_Default, /**< Default. 64MHz. */
#endif
} nrf_clock_xtalfreq_t;
/**
* @brief Interrupts.
*/
typedef enum
{
NRF_CLOCK_INT_HF_STARTED_MASK = CLOCK_INTENSET_HFCLKSTARTED_Msk, /**< Interrupt on HFCLKSTARTED event. */
NRF_CLOCK_INT_LF_STARTED_MASK = CLOCK_INTENSET_LFCLKSTARTED_Msk, /**< Interrupt on LFCLKSTARTED event. */
NRF_CLOCK_INT_DONE_MASK = CLOCK_INTENSET_DONE_Msk, /**< Interrupt on DONE event. */
NRF_CLOCK_INT_CTTO_MASK = CLOCK_INTENSET_CTTO_Msk /**< Interrupt on CTTO event. */
} nrf_clock_int_mask_t;
/**
* @brief Tasks.
*
* @details The NRF_CLOCK_TASK_LFCLKSTOP task cannot be set when the low-frequency clock is not running.
* The NRF_CLOCK_TASK_HFCLKSTOP task cannot be set when the high-frequency clock is not running.
*/
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
{
NRF_CLOCK_TASK_HFCLKSTART = offsetof(NRF_CLOCK_Type, TASKS_HFCLKSTART), /**< Start HFCLK clock source.*/
NRF_CLOCK_TASK_HFCLKSTOP = offsetof(NRF_CLOCK_Type, TASKS_HFCLKSTOP), /**< Stop HFCLK clock source.*/
NRF_CLOCK_TASK_LFCLKSTART = offsetof(NRF_CLOCK_Type, TASKS_LFCLKSTART), /**< Start LFCLK clock source.*/
NRF_CLOCK_TASK_LFCLKSTOP = offsetof(NRF_CLOCK_Type, TASKS_LFCLKSTOP), /**< Stop LFCLK clock source.*/
NRF_CLOCK_TASK_CAL = offsetof(NRF_CLOCK_Type, TASKS_CAL), /**< Start calibration of LFCLK RC oscillator.*/
NRF_CLOCK_TASK_CTSTART = offsetof(NRF_CLOCK_Type, TASKS_CTSTART), /**< Start calibration timer.*/
NRF_CLOCK_TASK_CTSTOP = offsetof(NRF_CLOCK_Type, TASKS_CTSTOP) /**< Stop calibration timer.*/
} nrf_clock_task_t; /*lint -restore */
/**
* @brief Events.
*/
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
{
NRF_CLOCK_EVENT_HFCLKSTARTED = offsetof(NRF_CLOCK_Type, EVENTS_HFCLKSTARTED), /**< HFCLK oscillator started.*/
NRF_CLOCK_EVENT_LFCLKSTARTED = offsetof(NRF_CLOCK_Type, EVENTS_LFCLKSTARTED), /**< LFCLK oscillator started.*/
NRF_CLOCK_EVENT_DONE = offsetof(NRF_CLOCK_Type, EVENTS_DONE), /**< Calibration of LFCLK RC oscillator completed.*/
NRF_CLOCK_EVENT_CTTO = offsetof(NRF_CLOCK_Type, EVENTS_CTTO) /**< Calibration timer time-out.*/
} nrf_clock_event_t; /*lint -restore */
/**
* @brief Function for enabling a specific interrupt.
*
* @param[in] int_mask Interrupt.
*/
__STATIC_INLINE void nrf_clock_int_enable(uint32_t int_mask);
/**
* @brief Function for disabling a specific interrupt.
*
* @param[in] int_mask Interrupt.
*/
__STATIC_INLINE void nrf_clock_int_disable(uint32_t int_mask);
/**
* @brief Function for retrieving the state of a specific interrupt.
*
* @param[in] int_mask Interrupt.
*
* @retval true If the interrupt is enabled.
* @retval false If the interrupt is not enabled.
*/
__STATIC_INLINE bool nrf_clock_int_enable_check(nrf_clock_int_mask_t int_mask);
/**
* @brief Function for retrieving the address of a specific task.
* @details This function can be used by the PPI module.
*
* @param[in] task Task.
*
* @return Address of the requested task register.
*/
__STATIC_INLINE uint32_t nrf_clock_task_address_get(nrf_clock_task_t task);
/**
* @brief Function for setting a specific task.
*
* @param[in] task Task.
*/
__STATIC_INLINE void nrf_clock_task_trigger(nrf_clock_task_t task);
/**
* @brief Function for retrieving the address of a specific event.
* @details This function can be used by the PPI module.
*
* @param[in] event Event.
*
* @return Address of the requested event register.
*/
__STATIC_INLINE uint32_t nrf_clock_event_address_get(nrf_clock_event_t event);
/**
* @brief Function for clearing a specific event.
*
* @param[in] event Event.
*/
__STATIC_INLINE void nrf_clock_event_clear(nrf_clock_event_t event);
/**
* @brief Function for retrieving the state of a specific event.
*
* @param[in] event Event.
*
* @retval true If the event is set.
* @retval false If the event is not set.
*/
__STATIC_INLINE bool nrf_clock_event_check(nrf_clock_event_t event);
/**
* @brief Function for changing the low-frequency clock source.
* @details This function cannot be called when the low-frequency clock is running.
*
* @param[in] source New low-frequency clock source.
*
*/
__STATIC_INLINE void nrf_clock_lf_src_set(nrf_clock_lfclk_t source);
/**
* @brief Function for retrieving the selected source for the low-frequency clock.
*
* @retval NRF_CLOCK_LFCLK_RC If the internal 32 kHz RC oscillator is the selected source for the low-frequency clock.
* @retval NRF_CLOCK_LFCLK_Xtal If an external 32 kHz crystal oscillator is the selected source for the low-frequency clock.
* @retval NRF_CLOCK_LFCLK_Synth If the internal 32 kHz synthesizer from the HFCLK is the selected source for the low-frequency clock.
*/
__STATIC_INLINE nrf_clock_lfclk_t nrf_clock_lf_src_get(void);
/**
* @brief Function for retrieving the active source of the low-frequency clock.
*
* @retval NRF_CLOCK_LFCLK_RC If the internal 32 kHz RC oscillator is the active source of the low-frequency clock.
* @retval NRF_CLOCK_LFCLK_Xtal If an external 32 kHz crystal oscillator is the active source of the low-frequency clock.
* @retval NRF_CLOCK_LFCLK_Synth If the internal 32 kHz synthesizer from the HFCLK is the active source of the low-frequency clock.
*/
__STATIC_INLINE nrf_clock_lfclk_t nrf_clock_lf_actv_src_get(void);
/**
* @brief Function for retrieving the clock source for the LFCLK clock when the task LKCLKSTART is triggered.
*
* @retval NRF_CLOCK_LFCLK_RC If the internal 32 kHz RC oscillator is running and generating the LFCLK clock.
* @retval NRF_CLOCK_LFCLK_Xtal If an external 32 kHz crystal oscillator is running and generating the LFCLK clock.
* @retval NRF_CLOCK_LFCLK_Synth If the internal 32 kHz synthesizer from the HFCLK is running and generating the LFCLK clock.
*/
__STATIC_INLINE nrf_clock_lfclk_t nrf_clock_lf_srccopy_get(void);
/**
* @brief Function for retrieving the state of the LFCLK clock.
*
* @retval false If the LFCLK clock is not running.
* @retval true If the LFCLK clock is running.
*/
__STATIC_INLINE bool nrf_clock_lf_is_running(void);
/**
* @brief Function for retrieving the trigger status of the task LFCLKSTART.
*
* @retval NRF_CLOCK_START_TASK_NOT_TRIGGERED If the task LFCLKSTART has not been triggered.
* @retval NRF_CLOCK_START_TASK_TRIGGERED If the task LFCLKSTART has been triggered.
*/
__STATIC_INLINE nrf_clock_start_task_status_t nrf_clock_lf_start_task_status_get(void);
/**
* @brief Function for retrieving the active source of the high-frequency clock.
*
* @retval NRF_CLOCK_HFCLK_LOW_ACCURACY If the internal 16 MHz RC oscillator is the active source of the high-frequency clock.
* @retval NRF_CLOCK_HFCLK_HIGH_ACCURACY If an external 16 MHz/32 MHz crystal oscillator is the active source of the high-frequency clock.
*/
__STATIC_INLINE nrf_clock_hfclk_t nrf_clock_hf_src_get(void);
/**
* @brief Function for retrieving the state of the HFCLK clock.
*
* @param[in] clk_src Clock source to be checked.
*
* @retval false If the HFCLK clock is not running.
* @retval true If the HFCLK clock is running.
*/
__STATIC_INLINE bool nrf_clock_hf_is_running(nrf_clock_hfclk_t clk_src);
/**
* @brief Function for retrieving the trigger status of the task HFCLKSTART.
*
* @retval NRF_CLOCK_START_TASK_NOT_TRIGGERED If the task HFCLKSTART has not been triggered.
* @retval NRF_CLOCK_START_TASK_TRIGGERED If the task HFCLKSTART has been triggered.
*/
__STATIC_INLINE nrf_clock_start_task_status_t nrf_clock_hf_start_task_status_get(void);
/**
* @brief Function for retrieving the frequency selection of the external crystal.
*
* @retval NRF_CLOCK_XTALFREQ_16MHz If a 16 MHz crystal is used as source for the HFCLK oscillator.
* @retval NRF_CLOCK_XTALFREQ_32MHz If a 32 MHz crystal is used as source for the HFCLK oscillator.
*/
__STATIC_INLINE nrf_clock_xtalfreq_t nrf_clock_xtalfreq_get(void);
/**
* @brief Function for changing the frequency selection of the external crystal.
*
* @param[in] xtalfreq New frequency selection for the external crystal.
*/
__STATIC_INLINE void nrf_clock_xtalfreq_set(nrf_clock_xtalfreq_t xtalfreq);
/**
* @brief Function for changing the calibration timer interval.
*
* @param[in] interval New calibration timer interval in 0.25 s resolution (range: 0.25 seconds to 31.75 seconds).
*/
__STATIC_INLINE void nrf_clock_cal_timer_timeout_set(uint32_t interval);
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE void nrf_clock_int_enable(uint32_t int_mask)
{
NRF_CLOCK->INTENSET = int_mask;
}
__STATIC_INLINE void nrf_clock_int_disable(uint32_t int_mask)
{
NRF_CLOCK->INTENCLR = int_mask;
}
__STATIC_INLINE bool nrf_clock_int_enable_check(nrf_clock_int_mask_t int_mask)
{
return (bool)(NRF_CLOCK->INTENCLR & int_mask);
}
__STATIC_INLINE uint32_t nrf_clock_task_address_get(nrf_clock_task_t task)
{
return ((uint32_t )NRF_CLOCK + task);
}
__STATIC_INLINE void nrf_clock_task_trigger(nrf_clock_task_t task)
{
*((volatile uint32_t *)((uint8_t *)NRF_CLOCK + task)) = NRF_CLOCK_TASK_TRIGGER;
}
__STATIC_INLINE uint32_t nrf_clock_event_address_get(nrf_clock_event_t event)
{
return ((uint32_t)NRF_CLOCK + event);
}
__STATIC_INLINE void nrf_clock_event_clear(nrf_clock_event_t event)
{
*((volatile uint32_t *)((uint8_t *)NRF_CLOCK + event)) = NRF_CLOCK_EVENT_CLEAR;
#if __CORTEX_M == 0x04
volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)NRF_CLOCK + event));
(void)dummy;
#endif
}
__STATIC_INLINE bool nrf_clock_event_check(nrf_clock_event_t event)
{
return (bool)*((volatile uint32_t *)((uint8_t *)NRF_CLOCK + event));
}
__STATIC_INLINE void nrf_clock_lf_src_set(nrf_clock_lfclk_t source)
{
NRF_CLOCK->LFCLKSRC =
(uint32_t)((source << CLOCK_LFCLKSRC_SRC_Pos) & CLOCK_LFCLKSRC_SRC_Msk);
}
__STATIC_INLINE nrf_clock_lfclk_t nrf_clock_lf_src_get(void)
{
return (nrf_clock_lfclk_t)((NRF_CLOCK->LFCLKSRC &
CLOCK_LFCLKSRC_SRC_Msk) >> CLOCK_LFCLKSRC_SRC_Pos);
}
__STATIC_INLINE nrf_clock_lfclk_t nrf_clock_lf_actv_src_get(void)
{
return (nrf_clock_lfclk_t)((NRF_CLOCK->LFCLKSTAT &
CLOCK_LFCLKSTAT_SRC_Msk) >> CLOCK_LFCLKSTAT_SRC_Pos);
}
__STATIC_INLINE nrf_clock_lfclk_t nrf_clock_lf_srccopy_get(void)
{
return (nrf_clock_lfclk_t)((NRF_CLOCK->LFCLKSRCCOPY &
CLOCK_LFCLKSRCCOPY_SRC_Msk) >> CLOCK_LFCLKSRCCOPY_SRC_Pos);
}
__STATIC_INLINE bool nrf_clock_lf_is_running(void)
{
return ((NRF_CLOCK->LFCLKSTAT &
CLOCK_LFCLKSTAT_STATE_Msk) >> CLOCK_LFCLKSTAT_STATE_Pos);
}
__STATIC_INLINE nrf_clock_start_task_status_t nrf_clock_lf_start_task_status_get(void)
{
return (nrf_clock_start_task_status_t)((NRF_CLOCK->LFCLKRUN &
CLOCK_LFCLKRUN_STATUS_Msk) >>
CLOCK_LFCLKRUN_STATUS_Pos);
}
__STATIC_INLINE nrf_clock_hfclk_t nrf_clock_hf_src_get(void)
{
return (nrf_clock_hfclk_t)((NRF_CLOCK->HFCLKSTAT &
CLOCK_HFCLKSTAT_SRC_Msk) >> CLOCK_HFCLKSTAT_SRC_Pos);
}
__STATIC_INLINE bool nrf_clock_hf_is_running(nrf_clock_hfclk_t clk_src)
{
return (NRF_CLOCK->HFCLKSTAT & (CLOCK_HFCLKSTAT_STATE_Msk | CLOCK_HFCLKSTAT_SRC_Msk)) ==
(CLOCK_HFCLKSTAT_STATE_Msk | (clk_src << CLOCK_HFCLKSTAT_SRC_Pos));
}
__STATIC_INLINE nrf_clock_start_task_status_t nrf_clock_hf_start_task_status_get(void)
{
return (nrf_clock_start_task_status_t)((NRF_CLOCK->HFCLKRUN &
CLOCK_HFCLKRUN_STATUS_Msk) >>
CLOCK_HFCLKRUN_STATUS_Pos);
}
__STATIC_INLINE nrf_clock_xtalfreq_t nrf_clock_xtalfreq_get(void)
{
#ifdef NRF51
return (nrf_clock_xtalfreq_t)((NRF_CLOCK->XTALFREQ &
CLOCK_XTALFREQ_XTALFREQ_Msk) >> CLOCK_XTALFREQ_XTALFREQ_Pos);
#elif defined NRF52
return NRF_CLOCK_XTALFREQ_Default;
#endif
}
__STATIC_INLINE void nrf_clock_xtalfreq_set(nrf_clock_xtalfreq_t xtalfreq)
{
#ifdef NRF51
NRF_CLOCK->XTALFREQ =
(uint32_t)((xtalfreq << CLOCK_XTALFREQ_XTALFREQ_Pos) & CLOCK_XTALFREQ_XTALFREQ_Msk);
#elif defined NRF52
return;
#endif
}
__STATIC_INLINE void nrf_clock_cal_timer_timeout_set(uint32_t interval)
{
NRF_CLOCK->CTIV = ((interval << CLOCK_CTIV_CTIV_Pos) & CLOCK_CTIV_CTIV_Msk);
}
#endif // SUPPRESS_INLINE_IMPLEMENTATION
/**
*@}
**/
#endif // NRF_CLOCK_H__

View File

@ -1,100 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 Implementation of AES ECB driver
*/
//lint -e438
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include "nrf.h"
#include "nrf_ecb.h"
static uint8_t ecb_data[48]; ///< ECB data structure for RNG peripheral to access.
static uint8_t* ecb_key; ///< Key: Starts at ecb_data
static uint8_t* ecb_cleartext; ///< Cleartext: Starts at ecb_data + 16 bytes.
static uint8_t* ecb_ciphertext; ///< Ciphertext: Starts at ecb_data + 32 bytes.
bool nrf_ecb_init(void)
{
ecb_key = ecb_data;
ecb_cleartext = ecb_data + 16;
ecb_ciphertext = ecb_data + 32;
NRF_ECB->ECBDATAPTR = (uint32_t)ecb_data;
return true;
}
bool nrf_ecb_crypt(uint8_t * dest_buf, const uint8_t * src_buf)
{
uint32_t counter = 0x1000000;
if(src_buf != ecb_cleartext)
{
memcpy(ecb_cleartext,src_buf,16);
}
NRF_ECB->EVENTS_ENDECB = 0;
NRF_ECB->TASKS_STARTECB = 1;
while(NRF_ECB->EVENTS_ENDECB == 0)
{
counter--;
if(counter == 0)
{
return false;
}
}
NRF_ECB->EVENTS_ENDECB = 0;
if(dest_buf != ecb_ciphertext)
{
memcpy(dest_buf,ecb_ciphertext,16);
}
return true;
}
void nrf_ecb_set_key(const uint8_t * key)
{
memcpy(ecb_key,key,16);
}

View File

@ -1,92 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 ECB driver API.
*/
#ifndef NRF_ECB_H__
#define NRF_ECB_H__
/**
* @defgroup nrf_ecb AES ECB encryption
* @{
* @ingroup nrf_drivers
* @brief Driver for the AES Electronic Code Book (ECB) peripheral.
*
* To encrypt and decrypt data, the peripheral must first be powered on
* using @ref nrf_ecb_init. Next, the key must be set using @ref nrf_ecb_set_key.
*/
#include <stdint.h>
/**
* @brief Function for initializing and powering on the ECB peripheral.
*
* This function allocates memory for the ECBDATAPTR.
* @retval true If initialization was successful.
* @retval false If powering on failed.
*/
bool nrf_ecb_init(void);
/**
* @brief Function for encrypting and decrypting 16-byte data using current key.
*
* This function avoids unnecessary copying of data if the parameters point to the
* correct locations in the ECB data structure.
*
* @param dst Result of encryption/decryption. 16 bytes will be written.
* @param src Source with 16-byte data to be encrypted/decrypted.
*
* @retval true If the encryption operation completed.
* @retval false If the encryption operation did not complete.
*/
bool nrf_ecb_crypt(uint8_t * dst, const uint8_t * src);
/**
* @brief Function for setting the key to be used for encryption and decryption.
*
* @param key Pointer to the key. 16 bytes will be read.
*/
void nrf_ecb_set_key(const uint8_t * key);
#endif // NRF_ECB_H__
/** @} */

View File

@ -1,674 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_GPIO_H__
#define NRF_GPIO_H__
#include "nrf.h"
#include <stdbool.h>
/**
* @defgroup nrf_gpio GPIO abstraction
* @{
* @ingroup nrf_drivers
* @brief GPIO pin abstraction and port abstraction for reading and writing byte-wise to GPIO ports.
*
* Here, the GPIO ports are defined as follows:
* - Port 0 -> pin 0-7
* - Port 1 -> pin 8-15
* - Port 2 -> pin 16-23
* - Port 3 -> pin 24-31
*/
#define NUMBER_OF_PINS 32
/**
* @brief Enumerator used for selecting between port 0 - 3.
*/
typedef enum
{
NRF_GPIO_PORT_SELECT_PORT0 = 0, ///< Port 0 (GPIO pin 0-7)
NRF_GPIO_PORT_SELECT_PORT1, ///< Port 1 (GPIO pin 8-15)
NRF_GPIO_PORT_SELECT_PORT2, ///< Port 2 (GPIO pin 16-23)
NRF_GPIO_PORT_SELECT_PORT3, ///< Port 3 (GPIO pin 24-31)
} nrf_gpio_port_select_t;
/**
* @brief Enumerator used for setting the direction of a GPIO port.
*/
typedef enum
{
NRF_GPIO_PORT_DIR_OUTPUT, ///< Output
NRF_GPIO_PORT_DIR_INPUT ///< Input
} nrf_gpio_port_dir_t;
/**
* @brief Pin direction definitions.
*/
typedef enum
{
NRF_GPIO_PIN_DIR_INPUT = GPIO_PIN_CNF_DIR_Input, ///< Input
NRF_GPIO_PIN_DIR_OUTPUT = GPIO_PIN_CNF_DIR_Output ///< Output
} nrf_gpio_pin_dir_t;
/**
* @brief Connection of input buffer
*/
typedef enum
{
NRF_GPIO_PIN_INPUT_CONNECT = GPIO_PIN_CNF_INPUT_Connect, ///< Connect input buffer
NRF_GPIO_PIN_INPUT_DISCONNECT = GPIO_PIN_CNF_INPUT_Disconnect ///< Disconnect input buffer
} nrf_gpio_pin_input_t;
/**
* @brief Enumerator used for selecting the pin to be pulled down or up at the time of pin configuration
*/
typedef enum
{
NRF_GPIO_PIN_NOPULL = GPIO_PIN_CNF_PULL_Disabled, ///< Pin pullup resistor disabled
NRF_GPIO_PIN_PULLDOWN = GPIO_PIN_CNF_PULL_Pulldown, ///< Pin pulldown resistor enabled
NRF_GPIO_PIN_PULLUP = GPIO_PIN_CNF_PULL_Pullup, ///< Pin pullup resistor enabled
} nrf_gpio_pin_pull_t;
/**
* @brief Enumerator used for selecting output drive mode
*/
typedef enum
{
NRF_GPIO_PIN_S0S1 = GPIO_PIN_CNF_DRIVE_S0S1, ///< !< Standard '0', standard '1'
NRF_GPIO_PIN_H0S1 = GPIO_PIN_CNF_DRIVE_H0S1, ///< !< High drive '0', standard '1'
NRF_GPIO_PIN_S0H1 = GPIO_PIN_CNF_DRIVE_S0H1, ///< !< Standard '0', high drive '1'
NRF_GPIO_PIN_H0H1 = GPIO_PIN_CNF_DRIVE_H0H1, ///< !< High drive '0', high 'drive '1''
NRF_GPIO_PIN_D0S1 = GPIO_PIN_CNF_DRIVE_D0S1, ///< !< Disconnect '0' standard '1'
NRF_GPIO_PIN_D0H1 = GPIO_PIN_CNF_DRIVE_D0H1, ///< !< Disconnect '0', high drive '1'
NRF_GPIO_PIN_S0D1 = GPIO_PIN_CNF_DRIVE_S0D1, ///< !< Standard '0'. disconnect '1'
NRF_GPIO_PIN_H0D1 = GPIO_PIN_CNF_DRIVE_H0D1, ///< !< High drive '0', disconnect '1'
} nrf_gpio_pin_drive_t;
/**
* @brief Enumerator used for selecting the pin to sense high or low level on the pin input.
*/
typedef enum
{
NRF_GPIO_PIN_NOSENSE = GPIO_PIN_CNF_SENSE_Disabled, ///< Pin sense level disabled.
NRF_GPIO_PIN_SENSE_LOW = GPIO_PIN_CNF_SENSE_Low, ///< Pin sense low level.
NRF_GPIO_PIN_SENSE_HIGH = GPIO_PIN_CNF_SENSE_High, ///< Pin sense high level.
} nrf_gpio_pin_sense_t;
/**
* @brief Function for configuring the GPIO pin range as outputs with normal drive strength.
* This function can be used to configure pin range as simple output with gate driving GPIO_PIN_CNF_DRIVE_S0S1 (normal cases).
*
* @param pin_range_start specifies the start number (inclusive) in the range of pin numbers to be configured (allowed values 0-30)
*
* @param pin_range_end specifies the end number (inclusive) in the range of pin numbers to be configured (allowed values 0-30)
*
* @note For configuring only one pin as output use @ref nrf_gpio_cfg_output
* Sense capability on the pin is disabled, and input is disconnected from the buffer as the pins are configured as output.
*/
__STATIC_INLINE void nrf_gpio_range_cfg_output(uint32_t pin_range_start, uint32_t pin_range_end);
/**
* @brief Function for configuring the GPIO pin range as inputs with given initial value set, hiding inner details.
* This function can be used to configure pin range as simple input.
*
* @param pin_range_start specifies the start number (inclusive) in the range of pin numbers to be configured (allowed values 0-30)
*
* @param pin_range_end specifies the end number (inclusive) in the range of pin numbers to be configured (allowed values 0-30)
*
* @param pull_config State of the pin range pull resistor (no pull, pulled down or pulled high)
*
* @note For configuring only one pin as input use @ref nrf_gpio_cfg_input
* Sense capability on the pin is disabled, and input is connected to buffer so that the GPIO->IN register is readable
*/
__STATIC_INLINE void nrf_gpio_range_cfg_input(uint32_t pin_range_start, uint32_t pin_range_end, nrf_gpio_pin_pull_t pull_config);
/**
* @brief Pin configuration function
*
* The main pin configuration function.
* This function allows to set any aspect in PIN_CNF register.
* @param pin_number Specifies the pin number (allowed values 0-31).
* @param dir Pin direction
* @param input Connect or disconnect input buffer
* @param pull Pull configuration
* @param drive Drive configuration
* @param sense Pin sensing mechanism
*/
__STATIC_INLINE void nrf_gpio_cfg(
uint32_t pin_number,
nrf_gpio_pin_dir_t dir,
nrf_gpio_pin_input_t input,
nrf_gpio_pin_pull_t pull,
nrf_gpio_pin_drive_t drive,
nrf_gpio_pin_sense_t sense);
/**
* @brief Function for configuring the given GPIO pin number as output with given initial value set, hiding inner details.
* This function can be used to configure pin range as simple input with gate driving GPIO_PIN_CNF_DRIVE_S0S1 (normal cases).
*
* @param pin_number specifies the pin number (allowed values 0-31)
*
* @note Sense capability on the pin is disabled, and input is disconnected from the buffer as the pins are configured as output.
*/
__STATIC_INLINE void nrf_gpio_cfg_output(uint32_t pin_number);
/**
* @brief Function for configuring the given GPIO pin number as input with given initial value set, hiding inner details.
* This function can be used to configure pin range as simple input with gate driving GPIO_PIN_CNF_DRIVE_S0S1 (normal cases).
*
* @param pin_number Specifies the pin number (allowed values 0-30).
* @param pull_config State of the pin range pull resistor (no pull, pulled down or pulled high).
*
* @note Sense capability on the pin is disabled, and input is connected to buffer so that the GPIO->IN register is readable
*/
__STATIC_INLINE void nrf_gpio_cfg_input(uint32_t pin_number, nrf_gpio_pin_pull_t pull_config);
/**
* @brief Function for reseting pin configuration to its default state.
*
* @param pin_number Specifies the pin number (allowed values 0-31).
*/
__STATIC_INLINE void nrf_gpio_cfg_default(uint32_t pin_number);
/**
* @brief Function for configuring the given GPIO pin number as a watcher. Only input is connected.
*
* @param pin_number Specifies the pin number (allowed values 0-31).
*
*/
__STATIC_INLINE void nrf_gpio_cfg_watcher(uint32_t pin_number);
/**
* @brief Function for disconnecting input for the given GPIO.
*
* @param pin_number Specifies the pin number (allowed values 0-31).
*
*/
__STATIC_INLINE void nrf_gpio_input_disconnect(uint32_t pin_number);
/**
* @brief Function for configuring the given GPIO pin number as input with given initial value set, hiding inner details.
* This function can be used to configure pin range as simple input with gate driving GPIO_PIN_CNF_DRIVE_S0S1 (normal cases).
* Sense capability on the pin is configurable, and input is connected to buffer so that the GPIO->IN register is readable.
*
* @param pin_number Specifies the pin number (allowed values 0-30).
* @param pull_config State of the pin pull resistor (no pull, pulled down or pulled high).
* @param sense_config Sense level of the pin (no sense, sense low or sense high).
*/
__STATIC_INLINE void nrf_gpio_cfg_sense_input(uint32_t pin_number, nrf_gpio_pin_pull_t pull_config, nrf_gpio_pin_sense_t sense_config);
/**
* @brief Function for configuring sense level for the given GPIO.
*
* @param pin_number Specifies the pin number of gpio pin numbers to be configured (allowed values 0-30).
* @param sense_config Sense configuration.
*
*/
__STATIC_INLINE void nrf_gpio_cfg_sense_set(uint32_t pin_number, nrf_gpio_pin_sense_t sense_config);
/**
* @brief Function for setting the direction for a GPIO pin.
*
* @param pin_number specifies the pin number (0-31) for which to
* set the direction.
*
* @param direction specifies the direction
*/
__STATIC_INLINE void nrf_gpio_pin_dir_set(uint32_t pin_number, nrf_gpio_pin_dir_t direction);
/**
* @brief Function for setting a GPIO pin.
*
* Note that the pin must be configured as an output for this
* function to have any effect.
*
* @param pin_number Specifies the pin number (0-31) to set.
*/
__STATIC_INLINE void nrf_gpio_pin_set(uint32_t pin_number);
/**
* @brief Function for setting GPIO pins.
*
* Note that the pins must be configured as outputs for this
* function to have any effect.
*
* @param pin_mask Specifies the pins to set.
*/
__STATIC_INLINE void nrf_gpio_pins_set(uint32_t pin_mask);
/**
* @brief Function for clearing a GPIO pin.
*
* Note that the pin must be configured as an output for this
* function to have any effect.
*
* @param pin_number Specifies the pin number (0-31) to clear.
*/
__STATIC_INLINE void nrf_gpio_pin_clear(uint32_t pin_number);
/**
* @brief Function for clearing GPIO pins.
*
* Note that the pins must be configured as outputs for this
* function to have any effect.
*
* @param pin_mask Specifies the pins to clear.
*/
__STATIC_INLINE void nrf_gpio_pins_clear(uint32_t pin_mask);
/**
* @brief Function for toggling a GPIO pin.
*
* Note that the pin must be configured as an output for this
* function to have any effect.
*
* @param pin_number Specifies the pin number (0-31) to toggle.
*/
__STATIC_INLINE void nrf_gpio_pin_toggle(uint32_t pin_number);
/**
* @brief Function for toggling GPIO pins.
*
* Note that the pins must be configured as outputs for this
* function to have any effect.
*
* @param pin_mask Specifies the pins to toggle.
*/
__STATIC_INLINE void nrf_gpio_pins_toggle(uint32_t pin_mask);
/**
* @brief Function for writing a value to a GPIO pin.
*
* Note that the pin must be configured as an output for this
* function to have any effect.
*
* @param pin_number specifies the pin number (0-31) to
* write.
*
* @param value specifies the value to be written to the pin.
* @arg 0 clears the pin
* @arg >=1 sets the pin.
*/
__STATIC_INLINE void nrf_gpio_pin_write(uint32_t pin_number, uint32_t value);
/**
* @brief Function for reading the input level of a GPIO pin.
*
* Note that the pin must have input connected for the value
* returned from this function to be valid.
*
* @param pin_number specifies the pin number (0-31) to
* read.
*
* @return
* @retval 0 if the pin input level is low.
* @retval 1 if the pin input level is high.
* @retval > 1 should never occur.
*/
__STATIC_INLINE uint32_t nrf_gpio_pin_read(uint32_t pin_number);
/**
* @brief Function for reading the input level of all GPIO pins.
*
* Note that the pin must have input connected for the value
* returned from this function to be valid.
*
* @retval Status of input of all pins
*/
__STATIC_INLINE uint32_t nrf_gpio_pins_read(void);
/**
* @brief Function for reading the sense configuration of a GPIO pin.
*
* @param pin_number specifies the pin number (0-31) to
* read.
*
* @retval Sense configuration
*/
__STATIC_INLINE nrf_gpio_pin_sense_t nrf_gpio_pin_sense_get(uint32_t pin_number);
/**
* @brief Generic function for writing a single byte of a 32 bit word at a given
* address.
*
* This function should not be called from outside the nrf_gpio
* abstraction layer.
*
* @param word_address is the address of the word to be written.
*
* @param byte_no is the word byte number (0-3) to be written.
*
* @param value is the value to be written to byte "byte_no" of word
* at address "word_address"
*/
__STATIC_INLINE void nrf_gpio_word_byte_write(volatile uint32_t * word_address, uint8_t byte_no, uint8_t value);
/**
* @brief Generic function for reading a single byte of a 32 bit word at a given
* address.
*
* This function should not be called from outside the nrf_gpio
* abstraction layer.
*
* @param word_address is the address of the word to be read.
*
* @param byte_no is the byte number (0-3) of the word to be read.
*
* @return byte "byte_no" of word at address "word_address".
*/
__STATIC_INLINE uint8_t nrf_gpio_word_byte_read(const volatile uint32_t* word_address, uint8_t byte_no);
/**
* @brief Function for setting the direction of a port.
*
* @param port is the port for which to set the direction.
*
* @param dir direction to be set for this port.
*/
__STATIC_INLINE void nrf_gpio_port_dir_set(nrf_gpio_port_select_t port, nrf_gpio_port_dir_t dir);
/**
* @brief Function for reading a GPIO port.
*
* @param port is the port to read.
*
* @return the input value on this port.
*/
__STATIC_INLINE uint8_t nrf_gpio_port_read(nrf_gpio_port_select_t port);
/**
* @brief Function for writing to a GPIO port.
*
* @param port is the port to write.
*
* @param value is the value to write to this port.
*
* @sa nrf_gpio_port_dir_set()
*/
__STATIC_INLINE void nrf_gpio_port_write(nrf_gpio_port_select_t port, uint8_t value);
/**
* @brief Function for setting individual pins on GPIO port.
*
* @param port is the port for which to set the pins.
*
* @param set_mask is a mask specifying which pins to set. A bit
* set to 1 indicates that the corresponding port pin shall be
* set.
*
* @sa nrf_gpio_port_dir_set()
*/
__STATIC_INLINE void nrf_gpio_port_set(nrf_gpio_port_select_t port, uint8_t set_mask);
/**
* @brief Function for clearing individual pins on GPIO port.
*
* @param port is the port for which to clear the pins.
*
* @param clr_mask is a mask specifying which pins to clear. A bit
* set to 1 indicates that the corresponding port pin shall be
* cleared.
*
* @sa nrf_gpio_port_dir_set()
*/
__STATIC_INLINE void nrf_gpio_port_clear(nrf_gpio_port_select_t port, uint8_t clr_mask);
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE void nrf_gpio_range_cfg_output(uint32_t pin_range_start, uint32_t pin_range_end)
{
/*lint -e{845} // A zero has been given as right argument to operator '|'" */
for (; pin_range_start <= pin_range_end; pin_range_start++)
{
nrf_gpio_cfg_output(pin_range_start);
}
}
__STATIC_INLINE void nrf_gpio_range_cfg_input(uint32_t pin_range_start, uint32_t pin_range_end, nrf_gpio_pin_pull_t pull_config)
{
/*lint -e{845} // A zero has been given as right argument to operator '|'" */
for (; pin_range_start <= pin_range_end; pin_range_start++)
{
nrf_gpio_cfg_input(pin_range_start, pull_config);
}
}
__STATIC_INLINE void nrf_gpio_cfg(
uint32_t pin_number,
nrf_gpio_pin_dir_t dir,
nrf_gpio_pin_input_t input,
nrf_gpio_pin_pull_t pull,
nrf_gpio_pin_drive_t drive,
nrf_gpio_pin_sense_t sense)
{
NRF_GPIO->PIN_CNF[pin_number] = ((uint32_t)dir << GPIO_PIN_CNF_DIR_Pos)
| ((uint32_t)input << GPIO_PIN_CNF_INPUT_Pos)
| ((uint32_t)pull << GPIO_PIN_CNF_PULL_Pos)
| ((uint32_t)drive << GPIO_PIN_CNF_DRIVE_Pos)
| ((uint32_t)sense << GPIO_PIN_CNF_SENSE_Pos);
}
__STATIC_INLINE void nrf_gpio_cfg_output(uint32_t pin_number)
{
nrf_gpio_cfg(
pin_number,
NRF_GPIO_PIN_DIR_OUTPUT,
NRF_GPIO_PIN_INPUT_DISCONNECT,
NRF_GPIO_PIN_NOPULL,
NRF_GPIO_PIN_S0S1,
NRF_GPIO_PIN_NOSENSE);
}
__STATIC_INLINE void nrf_gpio_cfg_input(uint32_t pin_number, nrf_gpio_pin_pull_t pull_config)
{
nrf_gpio_cfg(
pin_number,
NRF_GPIO_PIN_DIR_INPUT,
NRF_GPIO_PIN_INPUT_CONNECT,
pull_config,
NRF_GPIO_PIN_S0S1,
NRF_GPIO_PIN_NOSENSE);
}
__STATIC_INLINE void nrf_gpio_cfg_default(uint32_t pin_number)
{
nrf_gpio_cfg(
pin_number,
NRF_GPIO_PIN_DIR_INPUT,
NRF_GPIO_PIN_INPUT_DISCONNECT,
NRF_GPIO_PIN_NOPULL,
NRF_GPIO_PIN_S0S1,
NRF_GPIO_PIN_NOSENSE);
}
__STATIC_INLINE void nrf_gpio_cfg_watcher(uint32_t pin_number)
{
/*lint -e{845} // A zero has been given as right argument to operator '|'" */
uint32_t cnf = NRF_GPIO->PIN_CNF[pin_number] & ~GPIO_PIN_CNF_INPUT_Msk;
NRF_GPIO->PIN_CNF[pin_number] = cnf | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos);
}
__STATIC_INLINE void nrf_gpio_input_disconnect(uint32_t pin_number)
{
/*lint -e{845} // A zero has been given as right argument to operator '|'" */
uint32_t cnf = NRF_GPIO->PIN_CNF[pin_number] & ~GPIO_PIN_CNF_INPUT_Msk;
NRF_GPIO->PIN_CNF[pin_number] = cnf | (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos);
}
__STATIC_INLINE void nrf_gpio_cfg_sense_input(uint32_t pin_number, nrf_gpio_pin_pull_t pull_config, nrf_gpio_pin_sense_t sense_config)
{
nrf_gpio_cfg(
pin_number,
NRF_GPIO_PIN_DIR_INPUT,
NRF_GPIO_PIN_INPUT_CONNECT,
pull_config,
NRF_GPIO_PIN_S0S1,
sense_config);
}
__STATIC_INLINE void nrf_gpio_cfg_sense_set(uint32_t pin_number, nrf_gpio_pin_sense_t sense_config)
{
/*lint -e{845} // A zero has been given as right argument to operator '|'" */
//uint32_t cnf = NRF_GPIO->PIN_CNF[pin_number] & ~GPIO_PIN_CNF_SENSE_Msk;
NRF_GPIO->PIN_CNF[pin_number] &= ~GPIO_PIN_CNF_SENSE_Msk;
NRF_GPIO->PIN_CNF[pin_number] |= (sense_config << GPIO_PIN_CNF_SENSE_Pos);
}
__STATIC_INLINE void nrf_gpio_pin_dir_set(uint32_t pin_number, nrf_gpio_pin_dir_t direction)
{
if(direction == NRF_GPIO_PIN_DIR_INPUT)
{
nrf_gpio_cfg(
pin_number,
NRF_GPIO_PIN_DIR_INPUT,
NRF_GPIO_PIN_INPUT_CONNECT,
NRF_GPIO_PIN_NOPULL,
NRF_GPIO_PIN_S0S1,
NRF_GPIO_PIN_NOSENSE);
}
else
{
NRF_GPIO->DIRSET = (1UL << pin_number);
}
}
__STATIC_INLINE void nrf_gpio_pin_set(uint32_t pin_number)
{
NRF_GPIO->OUTSET = (1UL << pin_number);
}
__STATIC_INLINE void nrf_gpio_pins_set(uint32_t pin_mask)
{
NRF_GPIO->OUTSET = pin_mask;
}
__STATIC_INLINE void nrf_gpio_pin_clear(uint32_t pin_number)
{
NRF_GPIO->OUTCLR = (1UL << pin_number);
}
__STATIC_INLINE void nrf_gpio_pins_clear(uint32_t pin_mask)
{
NRF_GPIO->OUTCLR = pin_mask;
}
__STATIC_INLINE void nrf_gpio_pin_toggle(uint32_t pin_number)
{
nrf_gpio_pins_toggle(1UL << pin_number);
}
__STATIC_INLINE void nrf_gpio_pins_toggle(uint32_t pin_mask)
{
uint32_t pins_state = NRF_GPIO->OUT;
NRF_GPIO->OUTSET = (~pins_state & pin_mask);
NRF_GPIO->OUTCLR = ( pins_state & pin_mask);
}
__STATIC_INLINE void nrf_gpio_pin_write(uint32_t pin_number, uint32_t value)
{
if (value == 0)
{
nrf_gpio_pin_clear(pin_number);
}
else
{
nrf_gpio_pin_set(pin_number);
}
}
__STATIC_INLINE uint32_t nrf_gpio_pin_read(uint32_t pin_number)
{
return ((NRF_GPIO->IN >> pin_number) & 1UL);
}
__STATIC_INLINE uint32_t nrf_gpio_pins_read(void)
{
return NRF_GPIO->IN;
}
__STATIC_INLINE nrf_gpio_pin_sense_t nrf_gpio_pin_sense_get(uint32_t pin_number)
{
return (nrf_gpio_pin_sense_t)((NRF_GPIO->PIN_CNF[pin_number] & GPIO_PIN_CNF_SENSE_Msk) >> GPIO_PIN_CNF_SENSE_Pos);
}
__STATIC_INLINE void nrf_gpio_word_byte_write(volatile uint32_t * word_address, uint8_t byte_no, uint8_t value)
{
*((volatile uint8_t*)(word_address) + byte_no) = value;
}
__STATIC_INLINE uint8_t nrf_gpio_word_byte_read(const volatile uint32_t* word_address, uint8_t byte_no)
{
return (*((const volatile uint8_t*)(word_address) + byte_no));
}
__STATIC_INLINE void nrf_gpio_port_dir_set(nrf_gpio_port_select_t port, nrf_gpio_port_dir_t dir)
{
if (dir == NRF_GPIO_PORT_DIR_OUTPUT)
{
nrf_gpio_word_byte_write(&NRF_GPIO->DIRSET, port, 0xFF);
}
else
{
nrf_gpio_range_cfg_input(port*8, (port+1)*8-1, NRF_GPIO_PIN_NOPULL);
}
}
__STATIC_INLINE uint8_t nrf_gpio_port_read(nrf_gpio_port_select_t port)
{
return nrf_gpio_word_byte_read(&NRF_GPIO->IN, port);
}
__STATIC_INLINE void nrf_gpio_port_write(nrf_gpio_port_select_t port, uint8_t value)
{
nrf_gpio_word_byte_write(&NRF_GPIO->OUT, port, value);
}
__STATIC_INLINE void nrf_gpio_port_set(nrf_gpio_port_select_t port, uint8_t set_mask)
{
nrf_gpio_word_byte_write(&NRF_GPIO->OUTSET, port, set_mask);
}
__STATIC_INLINE void nrf_gpio_port_clear(nrf_gpio_port_select_t port, uint8_t clr_mask)
{
nrf_gpio_word_byte_write(&NRF_GPIO->OUTCLR, port, clr_mask);
}
#endif //SUPPRESS_INLINE_IMPLEMENTATION
/** @} */
#endif

View File

@ -1,418 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_GPIOTE_H__
#define NRF_GPIOTE_H__
#include "nrf.h"
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
/**
* @defgroup nrf_gpiote_abs GPIOTE abstraction
* @{
* @ingroup nrf_gpiote
* @brief GPIOTE abstraction for configuration of channels.
*/
#ifdef NRF51
#define NUMBER_OF_GPIO_TE 4
#elif defined(NRF52)
#define NUMBER_OF_GPIO_TE 8
#else
#error "Chip family not specified"
#endif
/**
* @enum nrf_gpiote_polarity_t
* @brief Polarity for the GPIOTE channel.
*/
typedef enum
{
NRF_GPIOTE_POLARITY_LOTOHI = GPIOTE_CONFIG_POLARITY_LoToHi, ///< Low to high.
NRF_GPIOTE_POLARITY_HITOLO = GPIOTE_CONFIG_POLARITY_HiToLo, ///< High to low.
NRF_GPIOTE_POLARITY_TOGGLE = GPIOTE_CONFIG_POLARITY_Toggle ///< Toggle.
} nrf_gpiote_polarity_t;
/**
* @enum nrf_gpiote_outinit_t
* @brief Initial output value for the GPIOTE channel.
*/
typedef enum
{
NRF_GPIOTE_INITIAL_VALUE_LOW = GPIOTE_CONFIG_OUTINIT_Low, ///< Low to high.
NRF_GPIOTE_INITIAL_VALUE_HIGH = GPIOTE_CONFIG_OUTINIT_High ///< High to low.
} nrf_gpiote_outinit_t;
/**
* @brief Tasks.
*/
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
{
NRF_GPIOTE_TASKS_OUT_0 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[0]), /**< Out task 0.*/
NRF_GPIOTE_TASKS_OUT_1 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[1]), /**< Out task 1.*/
NRF_GPIOTE_TASKS_OUT_2 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[2]), /**< Out task 2.*/
NRF_GPIOTE_TASKS_OUT_3 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[3]), /**< Out task 3.*/
#if (NUMBER_OF_GPIO_TE == 8)
NRF_GPIOTE_TASKS_OUT_4 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[4]), /**< Out task 4.*/
NRF_GPIOTE_TASKS_OUT_5 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[5]), /**< Out task 5.*/
NRF_GPIOTE_TASKS_OUT_6 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[6]), /**< Out task 6.*/
NRF_GPIOTE_TASKS_OUT_7 = offsetof(NRF_GPIOTE_Type, TASKS_OUT[7]), /**< Out task 7.*/
#endif
#ifdef NRF52
NRF_GPIOTE_TASKS_SET_0 = offsetof(NRF_GPIOTE_Type, TASKS_SET[0]), /**< Set task 0.*/
NRF_GPIOTE_TASKS_SET_1 = offsetof(NRF_GPIOTE_Type, TASKS_SET[1]), /**< Set task 1.*/
NRF_GPIOTE_TASKS_SET_2 = offsetof(NRF_GPIOTE_Type, TASKS_SET[2]), /**< Set task 2.*/
NRF_GPIOTE_TASKS_SET_3 = offsetof(NRF_GPIOTE_Type, TASKS_SET[3]), /**< Set task 3.*/
NRF_GPIOTE_TASKS_SET_4 = offsetof(NRF_GPIOTE_Type, TASKS_SET[4]), /**< Set task 4.*/
NRF_GPIOTE_TASKS_SET_5 = offsetof(NRF_GPIOTE_Type, TASKS_SET[5]), /**< Set task 5.*/
NRF_GPIOTE_TASKS_SET_6 = offsetof(NRF_GPIOTE_Type, TASKS_SET[6]), /**< Set task 6.*/
NRF_GPIOTE_TASKS_SET_7 = offsetof(NRF_GPIOTE_Type, TASKS_SET[7]), /**< Set task 7.*/
NRF_GPIOTE_TASKS_CLR_0 = offsetof(NRF_GPIOTE_Type, TASKS_CLR[0]), /**< Clear task 0.*/
NRF_GPIOTE_TASKS_CLR_1 = offsetof(NRF_GPIOTE_Type, TASKS_CLR[1]), /**< Clear task 1.*/
NRF_GPIOTE_TASKS_CLR_2 = offsetof(NRF_GPIOTE_Type, TASKS_CLR[2]), /**< Clear task 2.*/
NRF_GPIOTE_TASKS_CLR_3 = offsetof(NRF_GPIOTE_Type, TASKS_CLR[3]), /**< Clear task 3.*/
NRF_GPIOTE_TASKS_CLR_4 = offsetof(NRF_GPIOTE_Type, TASKS_CLR[4]), /**< Clear task 4.*/
NRF_GPIOTE_TASKS_CLR_5 = offsetof(NRF_GPIOTE_Type, TASKS_CLR[5]), /**< Clear task 5.*/
NRF_GPIOTE_TASKS_CLR_6 = offsetof(NRF_GPIOTE_Type, TASKS_CLR[6]), /**< Clear task 6.*/
NRF_GPIOTE_TASKS_CLR_7 = offsetof(NRF_GPIOTE_Type, TASKS_CLR[7]), /**< Clear task 7.*/
#endif
/*lint -restore*/
} nrf_gpiote_tasks_t;
/**
* @brief Events.
*/
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
{
NRF_GPIOTE_EVENTS_IN_0 = offsetof(NRF_GPIOTE_Type, EVENTS_IN[0]), /**< In event 0.*/
NRF_GPIOTE_EVENTS_IN_1 = offsetof(NRF_GPIOTE_Type, EVENTS_IN[1]), /**< In event 1.*/
NRF_GPIOTE_EVENTS_IN_2 = offsetof(NRF_GPIOTE_Type, EVENTS_IN[2]), /**< In event 2.*/
NRF_GPIOTE_EVENTS_IN_3 = offsetof(NRF_GPIOTE_Type, EVENTS_IN[3]), /**< In event 3.*/
#if (NUMBER_OF_GPIO_TE == 8)
NRF_GPIOTE_EVENTS_IN_4 = offsetof(NRF_GPIOTE_Type, EVENTS_IN[4]), /**< In event 4.*/
NRF_GPIOTE_EVENTS_IN_5 = offsetof(NRF_GPIOTE_Type, EVENTS_IN[5]), /**< In event 5.*/
NRF_GPIOTE_EVENTS_IN_6 = offsetof(NRF_GPIOTE_Type, EVENTS_IN[6]), /**< In event 6.*/
NRF_GPIOTE_EVENTS_IN_7 = offsetof(NRF_GPIOTE_Type, EVENTS_IN[7]), /**< In event 7.*/
#endif
NRF_GPIOTE_EVENTS_PORT = offsetof(NRF_GPIOTE_Type, EVENTS_PORT), /**< Port event.*/
/*lint -restore*/
} nrf_gpiote_events_t;
/**
* @enum nrf_gpiote_int_t
* @brief GPIOTE interrupts.
*/
typedef enum
{
NRF_GPIOTE_INT_IN0_MASK = GPIOTE_INTENSET_IN0_Msk, /**< GPIOTE interrupt from IN0. */
NRF_GPIOTE_INT_IN1_MASK = GPIOTE_INTENSET_IN1_Msk, /**< GPIOTE interrupt from IN1. */
NRF_GPIOTE_INT_IN2_MASK = GPIOTE_INTENSET_IN2_Msk, /**< GPIOTE interrupt from IN2. */
NRF_GPIOTE_INT_IN3_MASK = GPIOTE_INTENSET_IN3_Msk, /**< GPIOTE interrupt from IN3. */
#if (NUMBER_OF_GPIO_TE == 8)
NRF_GPIOTE_INT_IN4_MASK = GPIOTE_INTENSET_IN4_Msk, /**< GPIOTE interrupt from IN4. */
NRF_GPIOTE_INT_IN5_MASK = GPIOTE_INTENSET_IN5_Msk, /**< GPIOTE interrupt from IN5. */
NRF_GPIOTE_INT_IN6_MASK = GPIOTE_INTENSET_IN6_Msk, /**< GPIOTE interrupt from IN6. */
NRF_GPIOTE_INT_IN7_MASK = GPIOTE_INTENSET_IN7_Msk, /**< GPIOTE interrupt from IN7. */
#endif
NRF_GPIOTE_INT_PORT_MASK = (int)GPIOTE_INTENSET_PORT_Msk, /**< GPIOTE interrupt from PORT event. */
} nrf_gpiote_int_t;
#if (NUMBER_OF_GPIO_TE == 4)
#define NRF_GPIOTE_INT_IN_MASK (NRF_GPIOTE_INT_IN0_MASK | NRF_GPIOTE_INT_IN1_MASK |\
NRF_GPIOTE_INT_IN2_MASK | NRF_GPIOTE_INT_IN3_MASK)
#elif (NUMBER_OF_GPIO_TE == 8)
#define NRF_GPIOTE_INT_IN_MASK (NRF_GPIOTE_INT_IN0_MASK | NRF_GPIOTE_INT_IN1_MASK |\
NRF_GPIOTE_INT_IN2_MASK | NRF_GPIOTE_INT_IN3_MASK |\
NRF_GPIOTE_INT_IN4_MASK | NRF_GPIOTE_INT_IN5_MASK |\
NRF_GPIOTE_INT_IN6_MASK | NRF_GPIOTE_INT_IN7_MASK)
#else
#error "Unexpected number of GPIO Tasks and Events"
#endif
/**
* @brief Function for activating a specific GPIOTE task.
*
* @param[in] task Task.
*/
__STATIC_INLINE void nrf_gpiote_task_set(nrf_gpiote_tasks_t task);
/**
* @brief Function for getting the address of a specific GPIOTE task.
*
* @param[in] task Task.
*
* @returns Address.
*/
__STATIC_INLINE uint32_t nrf_gpiote_task_addr_get(nrf_gpiote_tasks_t task);
/**
* @brief Function for getting the state of a specific GPIOTE event.
*
* @param[in] event Event.
*/
__STATIC_INLINE bool nrf_gpiote_event_is_set(nrf_gpiote_events_t event);
/**
* @brief Function for clearing a specific GPIOTE event.
*
* @param[in] event Event.
*/
__STATIC_INLINE void nrf_gpiote_event_clear(nrf_gpiote_events_t event);
/**
* @brief Function for getting the address of a specific GPIOTE event.
*
* @param[in] event Event.
*
* @return Address
*/
__STATIC_INLINE uint32_t nrf_gpiote_event_addr_get(nrf_gpiote_events_t event);
/**@brief Function for enabling interrupts.
*
* @param[in] mask Interrupt mask to be enabled.
*/
__STATIC_INLINE void nrf_gpiote_int_enable(uint32_t mask);
/**@brief Function for disabling interrupts.
*
* @param[in] mask Interrupt mask to be disabled.
*/
__STATIC_INLINE void nrf_gpiote_int_disable(uint32_t mask);
/**@brief Function for checking if interrupts are enabled.
*
* @param[in] mask Mask of interrupt flags to check.
*
* @return Mask with enabled interrupts.
*/
__STATIC_INLINE uint32_t nrf_gpiote_int_is_enabled(uint32_t mask);
/**@brief Function for enabling a GPIOTE event.
*
* @param[in] idx Task-Event index.
*/
__STATIC_INLINE void nrf_gpiote_event_enable(uint32_t idx);
/**@brief Function for disabling a GPIOTE event.
*
* @param[in] idx Task-Event index.
*/
__STATIC_INLINE void nrf_gpiote_event_disable(uint32_t idx);
/**@brief Function for configuring a GPIOTE event.
*
* @param[in] idx Task-Event index.
* @param[in] pin Pin associated with event.
* @param[in] polarity Transition that should generate an event.
*/
__STATIC_INLINE void nrf_gpiote_event_configure(uint32_t idx, uint32_t pin,
nrf_gpiote_polarity_t polarity);
/**@brief Function for getting the pin associated with a GPIOTE event.
*
* @param[in] idx Task-Event index.
*
* @return Pin number.
*/
__STATIC_INLINE uint32_t nrf_gpiote_event_pin_get(uint32_t idx);
/**@brief Function for getting the polarity associated with a GPIOTE event.
*
* @param[in] idx Task-Event index.
*
* @return Polarity.
*/
__STATIC_INLINE nrf_gpiote_polarity_t nrf_gpiote_event_polarity_get(uint32_t idx);
/**@brief Function for enabling a GPIOTE task.
*
* @param[in] idx Task-Event index.
*/
__STATIC_INLINE void nrf_gpiote_task_enable(uint32_t idx);
/**@brief Function for disabling a GPIOTE task.
*
* @param[in] idx Task-Event index.
*/
__STATIC_INLINE void nrf_gpiote_task_disable(uint32_t idx);
/**@brief Function for configuring a GPIOTE task.
* @note Function is not configuring mode field so task is disabled after this function is called.
*
* @param[in] idx Task-Event index.
* @param[in] pin Pin associated with event.
* @param[in] polarity Transition that should generate an event.
* @param[in] init_val Initial value of pin.
*/
__STATIC_INLINE void nrf_gpiote_task_configure(uint32_t idx, uint32_t pin,
nrf_gpiote_polarity_t polarity,
nrf_gpiote_outinit_t init_val);
/**@brief Function for forcing a specific state on the pin connected to GPIOTE.
*
* @param[in] idx Task-Event index.
* @param[in] init_val Pin state.
*/
__STATIC_INLINE void nrf_gpiote_task_force(uint32_t idx, nrf_gpiote_outinit_t init_val);
/**@brief Function for resetting a GPIOTE task event configuration to the default state.
*
* @param[in] idx Task-Event index.
*/
__STATIC_INLINE void nrf_gpiote_te_default(uint32_t idx);
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE void nrf_gpiote_task_set(nrf_gpiote_tasks_t task)
{
*(__IO uint32_t *)((uint32_t)NRF_GPIOTE + task) = 0x1UL;
}
__STATIC_INLINE uint32_t nrf_gpiote_task_addr_get(nrf_gpiote_tasks_t task)
{
return ((uint32_t)NRF_GPIOTE + task);
}
__STATIC_INLINE bool nrf_gpiote_event_is_set(nrf_gpiote_events_t event)
{
return (*(uint32_t *)nrf_gpiote_event_addr_get(event) == 0x1UL) ? true : false;
}
__STATIC_INLINE void nrf_gpiote_event_clear(nrf_gpiote_events_t event)
{
*(uint32_t *)nrf_gpiote_event_addr_get(event) = 0;
#if __CORTEX_M == 0x04
volatile uint32_t dummy = *((volatile uint32_t *)nrf_gpiote_event_addr_get(event));
(void)dummy;
#endif
}
__STATIC_INLINE uint32_t nrf_gpiote_event_addr_get(nrf_gpiote_events_t event)
{
return ((uint32_t)NRF_GPIOTE + event);
}
__STATIC_INLINE void nrf_gpiote_int_enable(uint32_t mask)
{
NRF_GPIOTE->INTENSET = mask;
}
__STATIC_INLINE void nrf_gpiote_int_disable(uint32_t mask)
{
NRF_GPIOTE->INTENCLR = mask;
}
__STATIC_INLINE uint32_t nrf_gpiote_int_is_enabled(uint32_t mask)
{
return (NRF_GPIOTE->INTENSET & mask);
}
__STATIC_INLINE void nrf_gpiote_event_enable(uint32_t idx)
{
NRF_GPIOTE->CONFIG[idx] |= GPIOTE_CONFIG_MODE_Event;
}
__STATIC_INLINE void nrf_gpiote_event_disable(uint32_t idx)
{
NRF_GPIOTE->CONFIG[idx] &= ~GPIOTE_CONFIG_MODE_Event;
}
__STATIC_INLINE void nrf_gpiote_event_configure(uint32_t idx, uint32_t pin, nrf_gpiote_polarity_t polarity)
{
NRF_GPIOTE->CONFIG[idx] &= ~(GPIOTE_CONFIG_PSEL_Msk | GPIOTE_CONFIG_POLARITY_Msk);
NRF_GPIOTE->CONFIG[idx] |= ((pin << GPIOTE_CONFIG_PSEL_Pos) & GPIOTE_CONFIG_PSEL_Msk) |
((polarity << GPIOTE_CONFIG_POLARITY_Pos) & GPIOTE_CONFIG_POLARITY_Msk);
}
__STATIC_INLINE uint32_t nrf_gpiote_event_pin_get(uint32_t idx)
{
return ((NRF_GPIOTE->CONFIG[idx] & GPIOTE_CONFIG_PSEL_Msk) >> GPIOTE_CONFIG_PSEL_Pos);
}
__STATIC_INLINE nrf_gpiote_polarity_t nrf_gpiote_event_polarity_get(uint32_t idx)
{
return (nrf_gpiote_polarity_t)((NRF_GPIOTE->CONFIG[idx] & GPIOTE_CONFIG_POLARITY_Msk) >> GPIOTE_CONFIG_POLARITY_Pos);
}
__STATIC_INLINE void nrf_gpiote_task_enable(uint32_t idx)
{
uint32_t final_config = NRF_GPIOTE->CONFIG[idx] | GPIOTE_CONFIG_MODE_Task;
/* Workaround for the OUTINIT PAN. When nrf_gpiote_task_config() is called a glitch happens
on the GPIO if the GPIO in question is already assigned to GPIOTE and the pin is in the
correct state in GPIOTE but not in the OUT register. */
/* Configure channel to Pin31, not connected to the pin, and configure as a tasks that will set it to proper level */
NRF_GPIOTE->CONFIG[idx] = final_config | ((31 << GPIOTE_CONFIG_PSEL_Pos) & GPIOTE_CONFIG_PSEL_Msk);
__NOP();
__NOP();
__NOP();
NRF_GPIOTE->CONFIG[idx] = final_config;
}
__STATIC_INLINE void nrf_gpiote_task_disable(uint32_t idx)
{
NRF_GPIOTE->CONFIG[idx] &= ~GPIOTE_CONFIG_MODE_Task;
}
__STATIC_INLINE void nrf_gpiote_task_configure(uint32_t idx, uint32_t pin,
nrf_gpiote_polarity_t polarity,
nrf_gpiote_outinit_t init_val)
{
NRF_GPIOTE->CONFIG[idx] &= ~(GPIOTE_CONFIG_PSEL_Msk |
GPIOTE_CONFIG_POLARITY_Msk |
GPIOTE_CONFIG_OUTINIT_Msk);
NRF_GPIOTE->CONFIG[idx] |= ((pin << GPIOTE_CONFIG_PSEL_Pos) & GPIOTE_CONFIG_PSEL_Msk) |
((polarity << GPIOTE_CONFIG_POLARITY_Pos) & GPIOTE_CONFIG_POLARITY_Msk) |
((init_val << GPIOTE_CONFIG_OUTINIT_Pos) & GPIOTE_CONFIG_OUTINIT_Msk);
}
__STATIC_INLINE void nrf_gpiote_task_force(uint32_t idx, nrf_gpiote_outinit_t init_val)
{
NRF_GPIOTE->CONFIG[idx] = (NRF_GPIOTE->CONFIG[idx] & ~GPIOTE_CONFIG_OUTINIT_Msk)
| ((init_val << GPIOTE_CONFIG_OUTINIT_Pos) & GPIOTE_CONFIG_OUTINIT_Msk);
}
__STATIC_INLINE void nrf_gpiote_te_default(uint32_t idx)
{
NRF_GPIOTE->CONFIG[idx] = 0;
}
#endif //SUPPRESS_INLINE_IMPLEMENTATION
/** @} */
#endif

View File

@ -1,143 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 NMVC driver implementation
*/
#include <stdbool.h>
#include "nrf.h"
#include "nrf_nvmc.h"
void nrf_nvmc_page_erase(uint32_t address)
{
// Enable erase.
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Een;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
}
// Erase the page
NRF_NVMC->ERASEPAGE = address;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
}
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
}
}
void nrf_nvmc_write_byte(uint32_t address, uint8_t value)
{
uint32_t byte_shift = address & (uint32_t)0x03;
uint32_t address32 = address & ~byte_shift; // Address to the word this byte is in.
uint32_t value32 = (*(uint32_t*)address32 & ~((uint32_t)0xFF << (byte_shift << (uint32_t)3)));
value32 = value32 + ((uint32_t)value << (byte_shift << 3));
// Enable write.
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos);
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
}
*(uint32_t*)address32 = value32;
while(NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
}
NRF_NVMC->CONFIG = (NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos);
{
}
}
void nrf_nvmc_write_word(uint32_t address, uint32_t value)
{
// Enable write.
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){
}
*(uint32_t*)address = value;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){
}
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
}
}
void nrf_nvmc_write_bytes(uint32_t address, const uint8_t * src, uint32_t num_bytes)
{
uint32_t i;
for(i=0;i<num_bytes;i++)
{
nrf_nvmc_write_byte(address+i,src[i]);
}
}
void nrf_nvmc_write_words(uint32_t address, const uint32_t * src, uint32_t num_words)
{
uint32_t i;
// Enable write.
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
}
for(i=0;i<num_words;i++)
{
((uint32_t*)address)[i] = src[i];
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
}
}
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy)
{
}
}

View File

@ -1,116 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 NMVC driver API.
*/
#ifndef NRF_NVMC_H__
#define NRF_NVMC_H__
#include <stdint.h>
/**
* @defgroup nrf_nvmc Non-volatile memory controller
* @{
* @ingroup nrf_drivers
* @brief Driver for the NVMC peripheral.
*
* This driver allows writing to the non-volatile memory (NVM) regions
* of the chip. In order to write to NVM the controller must be powered
* on and the relevant page must be erased.
*
*/
/**
* @brief Erase a page in flash. This is required before writing to any
* address in the page.
*
* @param address Start address of the page.
*/
void nrf_nvmc_page_erase(uint32_t address);
/**
* @brief Write a single byte to flash.
*
* The function reads the word containing the byte, and then
* rewrites the entire word.
*
* @param address Address to write to.
* @param value Value to write.
*/
void nrf_nvmc_write_byte(uint32_t address , uint8_t value);
/**
* @brief Write a 32-bit word to flash.
* @param address Address to write to.
* @param value Value to write.
*/
void nrf_nvmc_write_word(uint32_t address, uint32_t value);
/**
* @brief Write consecutive bytes to flash.
*
* @param address Address to write to.
* @param src Pointer to data to copy from.
* @param num_bytes Number of bytes in src to write.
*/
void nrf_nvmc_write_bytes(uint32_t address, const uint8_t * src, uint32_t num_bytes);
/**
* @brief Write consecutive words to flash.
*
* @param address Address to write to.
* @param src Pointer to data to copy from.
* @param num_words Number of bytes in src to write.
*/
void nrf_nvmc_write_words(uint32_t address, const uint32_t * src, uint32_t num_words);
#endif // NRF_NVMC_H__
/** @} */

View File

@ -1,386 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_PDM_H_
#define NRF_PDM_H_
/**
* @defgroup nrf_pdm_hal PDM HAL
* @{
* @ingroup nrf_pdm
*
* @brief @tagAPI52 Hardware abstraction layer for accessing the pulse density modulation (PDM) peripheral.
*/
#include <stdbool.h>
#include <stddef.h>
#include "nrf.h"
#include "nrf_assert.h"
#define NRF_PDM_GAIN_MINIMUM 0x00
#define NRF_PDM_GAIN_DEFAULT 0x28
#define NRF_PDM_GAIN_MAXIMUM 0x50
typedef uint8_t nrf_pdm_gain_t;
/**
* @brief PDM tasks.
*/
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
{
NRF_PDM_TASK_START = offsetof(NRF_PDM_Type, TASKS_START), ///< Starts continuous PDM transfer.
NRF_PDM_TASK_STOP = offsetof(NRF_PDM_Type, TASKS_STOP) ///< Stops PDM transfer.
} nrf_pdm_task_t;
/**
* @brief PDM events.
*/
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
{
NRF_PDM_EVENT_STARTED = offsetof(NRF_PDM_Type, EVENTS_STARTED), ///< PDM transfer has started.
NRF_PDM_EVENT_STOPPED = offsetof(NRF_PDM_Type, EVENTS_STOPPED), ///< PDM transfer has finished.
NRF_PDM_EVENT_END = offsetof(NRF_PDM_Type, EVENTS_END) ///< The PDM has written the last sample specified by SAMPLE.MAXCNT (or the last sample after a STOP task has been received) to Data RAM.
} nrf_pdm_event_t;
/**
* @brief PDM interrupt masks.
*/
typedef enum
{
NRF_PDM_INT_STARTED = PDM_INTENSET_STARTED_Msk, ///< Interrupt on EVENTS_STARTED event.
NRF_PDM_INT_STOPPED = PDM_INTENSET_STOPPED_Msk, ///< Interrupt on EVENTS_STOPPED event.
NRF_PDM_INT_END = PDM_INTENSET_END_Msk ///< Interrupt on EVENTS_END event.
} nrf_pdm_int_mask_t;
/**
* @brief PDM clock frequency.
*/
typedef enum
{
NRF_PDM_FREQ_1000K = PDM_PDMCLKCTRL_FREQ_1000K, ///< PDM_CLK = 1.000 MHz.
NRF_PDM_FREQ_1032K = PDM_PDMCLKCTRL_FREQ_Default, ///< PDM_CLK = 1.032 MHz.
NRF_PDM_FREQ_1067K = PDM_PDMCLKCTRL_FREQ_1067K ///< PDM_CLK = 1.067 MHz.
} nrf_pdm_freq_t;
/**
* @brief PDM operation mode.
*/
typedef enum
{
NRF_PDM_MODE_STEREO = PDM_MODE_OPERATION_Stereo, ///< Sample and store one pair (Left + Right) of 16-bit samples per RAM word.
NRF_PDM_MODE_MONO = PDM_MODE_OPERATION_Mono ///< Sample and store two successive Left samples (16 bit each) per RAM word.
} nrf_pdm_mode_t;
/**
* @brief PDM sampling mode.
*/
typedef enum
{
NRF_PDM_EDGE_LEFTFALLING = PDM_MODE_EDGE_LeftFalling, ///< Left (or mono) is sampled on falling edge of PDM_CLK.
NRF_PDM_EDGE_LEFTRISING = PDM_MODE_EDGE_LeftRising ///< Left (or mono) is sampled on rising edge of PDM_CLK.
} nrf_pdm_edge_t;
/**
* @brief Function for triggering a PDM task.
*
* @param[in] pdm_task PDM task.
*/
__STATIC_INLINE void nrf_pdm_task_trigger(nrf_pdm_task_t pdm_task)
{
*((volatile uint32_t *)((uint8_t *)NRF_PDM + (uint32_t)pdm_task)) = 0x1UL;
}
/**
* @brief Function for getting the address of a PDM task register.
*
* @param[in] pdm_task PDM task.
*
* @return Address of the specified PDM task.
*/
__STATIC_INLINE uint32_t nrf_pdm_task_address_get(nrf_pdm_task_t pdm_task)
{
return (uint32_t)((uint8_t *)NRF_PDM + (uint32_t)pdm_task);
}
/**
* @brief Function for getting the state of a PDM event.
*
* @param[in] pdm_event PDM event.
*
* @return State of the specified PDM event.
*/
__STATIC_INLINE bool nrf_pdm_event_check(nrf_pdm_event_t pdm_event)
{
return (bool)*(volatile uint32_t *)((uint8_t *)NRF_PDM + (uint32_t)pdm_event);
}
/**
* @brief Function for clearing a PDM event.
*
* @param[in] pdm_event PDM event.
*/
__STATIC_INLINE void nrf_pdm_event_clear(nrf_pdm_event_t pdm_event)
{
*((volatile uint32_t *)((uint8_t *)NRF_PDM + (uint32_t)pdm_event)) = 0x0UL;
}
/**
* @brief Function for getting the address of a PDM event register.
*
* @param[in] pdm_event PDM event.
*
* @return Address of the specified PDM event.
*/
__STATIC_INLINE volatile uint32_t * nrf_pdm_event_address_get(nrf_pdm_event_t pdm_event)
{
return (volatile uint32_t *)((uint8_t *)NRF_PDM + (uint32_t)pdm_event);
}
/**
* @brief Function for enabling PDM interrupts.
*
* @param[in] pdm_int_mask Interrupts to enable.
*/
__STATIC_INLINE void nrf_pdm_int_enable(uint32_t pdm_int_mask)
{
NRF_PDM->INTENSET = pdm_int_mask;
}
/**
* @brief Function for retrieving the state of PDM interrupts.
*
* @param[in] pdm_int_mask Interrupts to check.
*
* @retval true If all specified interrupts are enabled.
* @retval false If at least one of the given interrupts is not enabled.
*/
__STATIC_INLINE bool nrf_pdm_int_enable_check(uint32_t pdm_int_mask)
{
return (bool)(NRF_PDM->INTENSET & pdm_int_mask);
}
/**
* @brief Function for disabling interrupts.
*
* @param pdm_int_mask Interrupts to disable.
*/
__STATIC_INLINE void nrf_pdm_int_disable(uint32_t pdm_int_mask)
{
NRF_PDM->INTENCLR = pdm_int_mask;
}
/**
* @brief Function for enabling the PDM peripheral.
*
* The PDM peripheral must be enabled before use.
*/
__STATIC_INLINE void nrf_pdm_enable(void)
{
NRF_PDM->ENABLE = (PDM_ENABLE_ENABLE_Enabled << PDM_ENABLE_ENABLE_Pos);
}
/**
* @brief Function for disabling the PDM peripheral.
*/
__STATIC_INLINE void nrf_pdm_disable(void)
{
NRF_PDM->ENABLE = (PDM_ENABLE_ENABLE_Disabled << PDM_ENABLE_ENABLE_Pos);
}
/**
* @brief Function for checking if the PDM peripheral is enabled.
*
* @retval true If the PDM peripheral is enabled.
* @retval false If the PDM peripheral is not enabled.
*/
__STATIC_INLINE bool nrf_pdm_enable_check(void)
{
return (NRF_PDM->ENABLE == (PDM_ENABLE_ENABLE_Enabled << PDM_ENABLE_ENABLE_Pos));
}
/**
* @brief Function for setting the PDM operation mode.
*
* @param[in] pdm_mode PDM operation mode.
* @param[in] pdm_edge PDM sampling mode.
*/
__STATIC_INLINE void nrf_pdm_mode_set(nrf_pdm_mode_t pdm_mode, nrf_pdm_edge_t pdm_edge)
{
NRF_PDM->MODE = ((pdm_mode << PDM_MODE_OPERATION_Pos) & PDM_MODE_OPERATION_Msk)
| ((pdm_edge << PDM_MODE_EDGE_Pos) & PDM_MODE_EDGE_Msk);
}
/**
* @brief Function for getting the PDM operation mode.
*
* @param[out] p_pdm_mode PDM operation mode.
* @param[out] p_pdm_edge PDM sampling mode.
*/
__STATIC_INLINE void nrf_pdm_mode_get(nrf_pdm_mode_t * p_pdm_mode, nrf_pdm_edge_t * p_pdm_edge)
{
uint32_t mode = NRF_PDM->MODE;
*p_pdm_mode = (nrf_pdm_mode_t)((mode & PDM_MODE_OPERATION_Msk ) >> PDM_MODE_OPERATION_Pos);
*p_pdm_edge = (nrf_pdm_edge_t)((mode & PDM_MODE_EDGE_Msk ) >> PDM_MODE_EDGE_Pos);
}
/**
* @brief Function for setting the PDM clock frequency.
*
* @param[in] pdm_freq PDM clock frequency.
*/
__STATIC_INLINE void nrf_pdm_clock_set(nrf_pdm_freq_t pdm_freq)
{
NRF_PDM->PDMCLKCTRL = ((pdm_freq << PDM_PDMCLKCTRL_FREQ_Pos) & PDM_PDMCLKCTRL_FREQ_Msk);
}
/**
* @brief Function for getting the PDM clock frequency.
*/
__STATIC_INLINE nrf_pdm_freq_t nrf_pdm_clock_get(void)
{
return (nrf_pdm_freq_t) ((NRF_PDM->PDMCLKCTRL << PDM_PDMCLKCTRL_FREQ_Pos) & PDM_PDMCLKCTRL_FREQ_Msk);
}
/**
* @brief Function for setting up the PDM pins.
*
* @param[in] psel_clk CLK pin number.
* @param[in] psel_din DIN pin number.
*/
__STATIC_INLINE void nrf_pdm_psel_connect(uint32_t psel_clk, uint32_t psel_din)
{
NRF_PDM->PSEL.CLK = ((psel_clk << PDM_PSEL_CLK_PIN_Pos) & PDM_PSEL_CLK_PIN_Msk)
| ((PDM_PSEL_CLK_CONNECT_Connected << PDM_PSEL_CLK_CONNECT_Pos) & PDM_PSEL_CLK_CONNECT_Msk);
NRF_PDM->PSEL.DIN = ((psel_din << PDM_PSEL_DIN_PIN_Pos) & PDM_PSEL_DIN_PIN_Msk)
| ((PDM_PSEL_DIN_CONNECT_Connected << PDM_PSEL_CLK_CONNECT_Pos) & PDM_PSEL_DIN_CONNECT_Msk);
}
/**
* @brief Function for disconnecting the PDM pins.
*/
__STATIC_INLINE void nrf_pdm_psel_disconnect()
{
NRF_PDM->PSEL.CLK = ((PDM_PSEL_CLK_CONNECT_Disconnected << PDM_PSEL_CLK_CONNECT_Pos)
& PDM_PSEL_CLK_CONNECT_Msk);
NRF_PDM->PSEL.DIN = ((PDM_PSEL_DIN_CONNECT_Disconnected << PDM_PSEL_DIN_CONNECT_Pos)
& PDM_PSEL_DIN_CONNECT_Msk);
}
/**
* @brief Function for setting the PDM gain.
*
* @param[in] gain_l Left channel gain.
* @param[in] gain_r Right channel gain.
*/
__STATIC_INLINE void nrf_pdm_gain_set(nrf_pdm_gain_t gain_l, nrf_pdm_gain_t gain_r)
{
NRF_PDM->GAINL = gain_l;
NRF_PDM->GAINR = gain_r;
}
/**
* @brief Function for getting the PDM gain.
*
* @param[out] p_gain_l Left channel gain.
* @param[out] p_gain_r Right channel gain.
*/
__STATIC_INLINE void nrf_pdm_gain_get(nrf_pdm_gain_t * p_gain_l, nrf_pdm_gain_t * p_gain_r)
{
*p_gain_l = NRF_PDM->GAINL;
*p_gain_r = NRF_PDM->GAINR;
}
/**
* @brief Function for setting the PDM sample buffer.
*
* @param[in] p_buffer Pointer to the RAM address where samples should be written with EasyDMA.
* @param[in] num Number of samples to allocate memory for in EasyDMA mode.
*
* The amount of allocated RAM depends on the operation mode.
* - For stereo mode: N 32-bit words.
* - For mono mode: Ceil(N/2) 32-bit words.
*/
__STATIC_INLINE void nrf_pdm_buffer_set(uint32_t * p_buffer, uint32_t num)
{
NRF_PDM->SAMPLE.PTR = (uint32_t)p_buffer;
NRF_PDM->SAMPLE.MAXCNT = num;
}
/**
* @brief Function for getting the current PDM sample buffer address.
*
* @return Pointer to the current sample buffer.
*/
__STATIC_INLINE uint32_t * nrf_pdm_buffer_get()
{
return (uint32_t *)NRF_PDM->SAMPLE.PTR;
}
/**
*@}
**/
#endif /* NRF_PDM_H_ */

View File

@ -1,429 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_PPI_H__
#define NRF_PPI_H__
#include <stddef.h>
#include "nrf.h"
/**
* @defgroup nrf_ppi_hal PPI HAL
* @{
* @ingroup nrf_ppi
* @brief Hardware access layer for setting up Programmable Peripheral Interconnect (PPI) channels.
*/
#define NRF_PPI_TASK_SET (1UL)
/**
* @enum nrf_ppi_channel_t
* @brief PPI channels.
*/
typedef enum
{
NRF_PPI_CHANNEL0 = PPI_CHEN_CH0_Pos, /**< Channel 0. */
NRF_PPI_CHANNEL1 = PPI_CHEN_CH1_Pos, /**< Channel 1. */
NRF_PPI_CHANNEL2 = PPI_CHEN_CH2_Pos, /**< Channel 2. */
NRF_PPI_CHANNEL3 = PPI_CHEN_CH3_Pos, /**< Channel 3. */
NRF_PPI_CHANNEL4 = PPI_CHEN_CH4_Pos, /**< Channel 4. */
NRF_PPI_CHANNEL5 = PPI_CHEN_CH5_Pos, /**< Channel 5. */
NRF_PPI_CHANNEL6 = PPI_CHEN_CH6_Pos, /**< Channel 6. */
NRF_PPI_CHANNEL7 = PPI_CHEN_CH7_Pos, /**< Channel 7. */
NRF_PPI_CHANNEL8 = PPI_CHEN_CH8_Pos, /**< Channel 8. */
NRF_PPI_CHANNEL9 = PPI_CHEN_CH9_Pos, /**< Channel 9. */
NRF_PPI_CHANNEL10 = PPI_CHEN_CH10_Pos, /**< Channel 10. */
NRF_PPI_CHANNEL11 = PPI_CHEN_CH11_Pos, /**< Channel 11. */
NRF_PPI_CHANNEL12 = PPI_CHEN_CH12_Pos, /**< Channel 12. */
NRF_PPI_CHANNEL13 = PPI_CHEN_CH13_Pos, /**< Channel 13. */
NRF_PPI_CHANNEL14 = PPI_CHEN_CH14_Pos, /**< Channel 14. */
NRF_PPI_CHANNEL15 = PPI_CHEN_CH15_Pos, /**< Channel 15. */
#ifdef NRF52
NRF_PPI_CHANNEL16 = PPI_CHEN_CH16_Pos, /**< Channel 16. */
NRF_PPI_CHANNEL17 = PPI_CHEN_CH17_Pos, /**< Channel 17. */
NRF_PPI_CHANNEL18 = PPI_CHEN_CH18_Pos, /**< Channel 18. */
NRF_PPI_CHANNEL19 = PPI_CHEN_CH19_Pos, /**< Channel 19. */
#endif
NRF_PPI_CHANNEL20 = PPI_CHEN_CH20_Pos, /**< Channel 20. */
NRF_PPI_CHANNEL21 = PPI_CHEN_CH21_Pos, /**< Channel 21. */
NRF_PPI_CHANNEL22 = PPI_CHEN_CH22_Pos, /**< Channel 22. */
NRF_PPI_CHANNEL23 = PPI_CHEN_CH23_Pos, /**< Channel 23. */
NRF_PPI_CHANNEL24 = PPI_CHEN_CH24_Pos, /**< Channel 24. */
NRF_PPI_CHANNEL25 = PPI_CHEN_CH25_Pos, /**< Channel 25. */
NRF_PPI_CHANNEL26 = PPI_CHEN_CH26_Pos, /**< Channel 26. */
NRF_PPI_CHANNEL27 = PPI_CHEN_CH27_Pos, /**< Channel 27. */
NRF_PPI_CHANNEL28 = PPI_CHEN_CH28_Pos, /**< Channel 28. */
NRF_PPI_CHANNEL29 = PPI_CHEN_CH29_Pos, /**< Channel 29. */
NRF_PPI_CHANNEL30 = PPI_CHEN_CH30_Pos, /**< Channel 30. */
NRF_PPI_CHANNEL31 = PPI_CHEN_CH31_Pos /**< Channel 31. */
} nrf_ppi_channel_t;
/**
* @enum nrf_ppi_channel_group_t
* @brief PPI channel groups.
*/
typedef enum
{
NRF_PPI_CHANNEL_GROUP0 = 0, /**< Channel group 0. */
NRF_PPI_CHANNEL_GROUP1 = 1, /**< Channel group 1. */
NRF_PPI_CHANNEL_GROUP2 = 2, /**< Channel group 2. */
NRF_PPI_CHANNEL_GROUP3 = 3, /**< Channel group 3. */
#ifdef NRF52
NRF_PPI_CHANNEL_GROUP4 = 4, /**< Channel group 4. */
NRF_PPI_CHANNEL_GROUP5 = 5 /**< Channel group 5. */
#endif
} nrf_ppi_channel_group_t;
/**
* @enum nrf_ppi_channel_include_t
* @brief Definition of which PPI channels belong to a group.
*/
typedef enum
{
NRF_PPI_CHANNEL_EXCLUDE = PPI_CHG_CH0_Excluded, /**< Channel excluded from a group. */
NRF_PPI_CHANNEL_INCLUDE = PPI_CHG_CH0_Included /**< Channel included in a group. */
} nrf_ppi_channel_include_t;
/**
* @enum nrf_ppi_channel_enable_t
* @brief Definition if a PPI channel is enabled.
*/
typedef enum
{
NRF_PPI_CHANNEL_DISABLED = PPI_CHEN_CH0_Disabled, /**< Channel disabled. */
NRF_PPI_CHANNEL_ENABLED = PPI_CHEN_CH0_Enabled /**< Channel enabled. */
} nrf_ppi_channel_enable_t;
/**
* @enum nrf_ppi_task_t
* @brief PPI tasks.
*/
typedef enum
{
/*lint -save -e30 -esym(628,__INTADDR__)*/
NRF_PPI_TASK_CHG0_EN = offsetof(NRF_PPI_Type, TASKS_CHG[0].EN), /**< Task for enabling channel group 0 */
NRF_PPI_TASK_CHG0_DIS = offsetof(NRF_PPI_Type, TASKS_CHG[0].DIS), /**< Task for disabling channel group 0 */
NRF_PPI_TASK_CHG1_EN = offsetof(NRF_PPI_Type, TASKS_CHG[1].EN), /**< Task for enabling channel group 1 */
NRF_PPI_TASK_CHG1_DIS = offsetof(NRF_PPI_Type, TASKS_CHG[1].DIS), /**< Task for disabling channel group 1 */
NRF_PPI_TASK_CHG2_EN = offsetof(NRF_PPI_Type, TASKS_CHG[2].EN), /**< Task for enabling channel group 2 */
NRF_PPI_TASK_CHG2_DIS = offsetof(NRF_PPI_Type, TASKS_CHG[2].DIS), /**< Task for disabling channel group 2 */
NRF_PPI_TASK_CHG3_EN = offsetof(NRF_PPI_Type, TASKS_CHG[3].EN), /**< Task for enabling channel group 3 */
NRF_PPI_TASK_CHG3_DIS = offsetof(NRF_PPI_Type, TASKS_CHG[3].DIS), /**< Task for disabling channel group 3 */
#ifdef NRF52
NRF_PPI_TASK_CHG4_EN = offsetof(NRF_PPI_Type, TASKS_CHG[4].EN), /**< Task for enabling channel group 4 */
NRF_PPI_TASK_CHG4_DIS = offsetof(NRF_PPI_Type, TASKS_CHG[4].DIS), /**< Task for disabling channel group 4 */
NRF_PPI_TASK_CHG5_EN = offsetof(NRF_PPI_Type, TASKS_CHG[5].EN), /**< Task for enabling channel group 5 */
NRF_PPI_TASK_CHG5_DIS = offsetof(NRF_PPI_Type, TASKS_CHG[5].DIS) /**< Task for disabling channel group 5 */
#endif
/*lint -restore*/
} nrf_ppi_task_t;
/**
* @brief Function for enabling a given PPI channel.
*
* @details This function enables only one channel.
*
* @param[in] channel Channel to enable.
*
* */
__STATIC_INLINE void nrf_ppi_channel_enable(nrf_ppi_channel_t channel)
{
NRF_PPI->CHENSET = PPI_CHENSET_CH0_Set << ((uint32_t) channel);
}
/**
* @brief Function for disabling a given PPI channel.
*
* @details This function disables only one channel.
*
* @param[in] channel Channel to disable.
*/
__STATIC_INLINE void nrf_ppi_channel_disable(nrf_ppi_channel_t channel)
{
NRF_PPI->CHENCLR = PPI_CHENCLR_CH0_Clear << ((uint32_t) channel);
}
/**
* @brief Function for checking if a given PPI channel is enabled.
*
* @details This function checks only one channel.
*
* @param[in] channel Channel to check.
*
* @retval NRF_PPI_CHANNEL_ENABLED If the channel is enabled.
* @retval NRF_PPI_CHANNEL_DISABLED If the channel is not enabled.
*
*/
__STATIC_INLINE nrf_ppi_channel_enable_t nrf_ppi_channel_enable_get(nrf_ppi_channel_t channel)
{
if (NRF_PPI->CHEN & (PPI_CHEN_CH0_Msk << ((uint32_t) channel)))
{
return NRF_PPI_CHANNEL_ENABLED;
}
else
{
return NRF_PPI_CHANNEL_DISABLED;
}
}
/**
* @brief Function for disabling all PPI channels.
*/
__STATIC_INLINE void nrf_ppi_channel_disable_all(void)
{
NRF_PPI->CHENCLR = ((uint32_t)0xFFFFFFFFuL);
}
/**
* @brief Function for disabling multiple PPI channels.
*
* @param[in] mask Channel mask.
*/
__STATIC_INLINE void nrf_ppi_channels_disable(uint32_t mask)
{
NRF_PPI->CHENCLR = mask;
}
/**
* @brief Function for setting up event and task endpoints for a given PPI channel.
*
* @param[in] eep Event register address.
*
* @param[in] tep Task register address.
*
* @param[in] channel Channel to which the given endpoints are assigned.
*/
__STATIC_INLINE void nrf_ppi_channel_endpoint_setup(nrf_ppi_channel_t channel,
uint32_t eep,
uint32_t tep)
{
NRF_PPI->CH[(uint32_t) channel].EEP = eep;
NRF_PPI->CH[(uint32_t) channel].TEP = tep;
}
#ifdef NRF52
/**
* @brief Function for setting up task endpoint for a given PPI fork.
*
* @param[in] fork_tep Task register address.
*
* @param[in] channel Channel to which the given fork endpoint is assigned.
*/
__STATIC_INLINE void nrf_ppi_fork_endpoint_setup(nrf_ppi_channel_t channel,
uint32_t fork_tep)
{
NRF_PPI->FORK[(uint32_t) channel].TEP = fork_tep;
}
/**
* @brief Function for setting up event and task endpoints for a given PPI channel and fork.
*
* @param[in] eep Event register address.
*
* @param[in] tep Task register address.
*
* @param[in] fork_tep Fork task register address (register value).
*
* @param[in] channel Channel to which the given endpoints are assigned.
*/
__STATIC_INLINE void nrf_ppi_channel_and_fork_endpoint_setup(nrf_ppi_channel_t channel,
uint32_t eep,
uint32_t tep,
uint32_t fork_tep)
{
nrf_ppi_channel_endpoint_setup(channel, eep, tep);
nrf_ppi_fork_endpoint_setup(channel, fork_tep);
}
#endif
/**
* @brief Function for including a PPI channel in a channel group.
*
* @details This function adds only one channel to the group.
*
* @param[in] channel Channel to be included in the group.
*
* @param[in] channel_group Channel group.
*
*/
__STATIC_INLINE void nrf_ppi_channel_include_in_group(nrf_ppi_channel_t channel,
nrf_ppi_channel_group_t channel_group)
{
NRF_PPI->CHG[(uint32_t) channel_group] =
NRF_PPI->CHG[(uint32_t) channel_group] | (PPI_CHG_CH0_Included << ((uint32_t) channel));
}
/**
* @brief Function for including multiple PPI channels in a channel group.
*
* @details This function adds all specified channels to the group.
*
* @param[in] channel_mask Channels to be included in the group.
*
* @param[in] channel_group Channel group.
*
*/
__STATIC_INLINE void nrf_ppi_channels_include_in_group(uint32_t channel_mask,
nrf_ppi_channel_group_t channel_group)
{
NRF_PPI->CHG[(uint32_t) channel_group] =
NRF_PPI->CHG[(uint32_t) channel_group] | (channel_mask);
}
/**
* @brief Function for removing a PPI channel from a channel group.
*
* @details This function removes only one channel from the group.
*
* @param[in] channel Channel to be removed from the group.
*
* @param[in] channel_group Channel group.
*/
__STATIC_INLINE void nrf_ppi_channel_remove_from_group(nrf_ppi_channel_t channel,
nrf_ppi_channel_group_t channel_group)
{
NRF_PPI->CHG[(uint32_t) channel_group] =
NRF_PPI->CHG[(uint32_t) channel_group] & ~(PPI_CHG_CH0_Included << ((uint32_t) channel));
}
/**
* @brief Function for removing multiple PPI channels from a channel group.
*
* @details This function removes all specified channels from the group.
*
* @param[in] channel_mask Channels to be removed from the group.
*
* @param[in] channel_group Channel group.
*/
__STATIC_INLINE void nrf_ppi_channels_remove_from_group(uint32_t channel_mask,
nrf_ppi_channel_group_t channel_group)
{
NRF_PPI->CHG[(uint32_t) channel_group] =
NRF_PPI->CHG[(uint32_t) channel_group] & ~(channel_mask);
}
/**
* @brief Function for removing all PPI channels from a channel group.
*
* @param[in] group Channel group.
*
*/
__STATIC_INLINE void nrf_ppi_channel_group_clear(nrf_ppi_channel_group_t group)
{
NRF_PPI->CHG[(uint32_t) group] = 0;
}
/**
* @brief Function for enabling a channel group.
*
* @param[in] group Channel group.
*
*/
__STATIC_INLINE void nrf_ppi_group_enable(nrf_ppi_channel_group_t group)
{
NRF_PPI->TASKS_CHG[(uint32_t) group].EN = NRF_PPI_TASK_SET;
}
/**
* @brief Function for disabling a channel group.
*
* @param[in] group Channel group.
*
*/
__STATIC_INLINE void nrf_ppi_group_disable(nrf_ppi_channel_group_t group)
{
NRF_PPI->TASKS_CHG[(uint32_t) group].DIS = NRF_PPI_TASK_SET;
}
/**
* @brief Function for setting a PPI task.
*
* @param[in] ppi_task PPI task to set.
*/
__STATIC_INLINE void nrf_ppi_task_trigger(nrf_ppi_task_t ppi_task)
{
*((volatile uint32_t *) ((uint8_t *) NRF_PPI_BASE + (uint32_t) ppi_task)) = NRF_PPI_TASK_SET;
}
/**
* @brief Function for returning the address of a specific PPI task register.
*
* @param[in] ppi_task PPI task.
*/
__STATIC_INLINE uint32_t * nrf_ppi_task_address_get(nrf_ppi_task_t ppi_task)
{
return (uint32_t *) ((uint8_t *) NRF_PPI_BASE + (uint32_t) ppi_task);
}
/**
* @brief Function for returning the PPI enable task address of a specific group.
*
* @param[in] group PPI group.
*/
__STATIC_INLINE uint32_t * nrf_ppi_task_group_enable_address_get(nrf_ppi_channel_group_t group)
{
return (uint32_t *) &NRF_PPI->TASKS_CHG[(uint32_t) group].EN;
}
/**
* @brief Function for returning the PPI disable task address of a specific group.
*
* @param[in] group PPI group.
*/
__STATIC_INLINE uint32_t * nrf_ppi_task_group_disable_address_get(nrf_ppi_channel_group_t group)
{
return (uint32_t *) &NRF_PPI->TASKS_CHG[(uint32_t) group].DIS;
}
/**
*@}
**/
/*lint --flb "Leave library region" */
#endif // NRF_PPI_H__

View File

@ -1,665 +0,0 @@
/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
/**
* @defgroup nrf_pwm_hal PWM HAL
* @{
* @ingroup nrf_pwm
*
* @brief @tagAPI52 Hardware access layer for managing the Pulse Width Modulation (PWM)
* peripheral.
*/
#ifndef NRF_PWM_H__
#define NRF_PWM_H__
#ifdef NRF52
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "nrf.h"
#include "nrf_assert.h"
/**
* @brief This value can be provided as a parameter for the @ref nrf_pwm_pins_set
* function call to specify that a given output channel shall not be
* connected to a physical pin.
*/
#define NRF_PWM_PIN_NOT_CONNECTED 0xFFFFFFFF
/**
* @brief Number of channels in each PWM instance.
*/
#define NRF_PWM_CHANNEL_COUNT 4
/**
* @brief PWM tasks.
*/
typedef enum
{
/*lint -save -e30*/
NRF_PWM_TASK_STOP = offsetof(NRF_PWM_Type, TASKS_STOP), ///< Stops PWM pulse generation on all channels at the end of the current PWM period, and stops the sequence playback.
NRF_PWM_TASK_SEQSTART0 = offsetof(NRF_PWM_Type, TASKS_SEQSTART[0]), ///< Starts playback of sequence 0.
NRF_PWM_TASK_SEQSTART1 = offsetof(NRF_PWM_Type, TASKS_SEQSTART[1]), ///< Starts playback of sequence 1.
NRF_PWM_TASK_NEXTSTEP = offsetof(NRF_PWM_Type, TASKS_NEXTSTEP) ///< Steps by one value in the current sequence if the decoder is set to @ref NRF_PWM_STEP_TRIGGERED mode.
/*lint -restore*/
} nrf_pwm_task_t;
/**
* @brief PWM events.
*/
typedef enum
{
/*lint -save -e30*/
NRF_PWM_EVENT_STOPPED = offsetof(NRF_PWM_Type, EVENTS_STOPPED), ///< Response to STOP task, emitted when PWM pulses are no longer generated.
NRF_PWM_EVENT_SEQSTARTED0 = offsetof(NRF_PWM_Type, EVENTS_SEQSTARTED[0]), ///< First PWM period started on sequence 0.
NRF_PWM_EVENT_SEQSTARTED1 = offsetof(NRF_PWM_Type, EVENTS_SEQSTARTED[1]), ///< First PWM period started on sequence 1.
NRF_PWM_EVENT_SEQEND0 = offsetof(NRF_PWM_Type, EVENTS_SEQEND[0]), ///< Emitted at the end of every sequence 0 when its last value has been read from RAM.
NRF_PWM_EVENT_SEQEND1 = offsetof(NRF_PWM_Type, EVENTS_SEQEND[1]), ///< Emitted at the end of every sequence 1 when its last value has been read from RAM.
NRF_PWM_EVENT_PWMPERIODEND = offsetof(NRF_PWM_Type, EVENTS_PWMPERIODEND), ///< Emitted at the end of each PWM period.
NRF_PWM_EVENT_LOOPSDONE = offsetof(NRF_PWM_Type, EVENTS_LOOPSDONE) ///< Concatenated sequences have been played the requested number of times.
/*lint -restore*/
} nrf_pwm_event_t;
/**
* @brief PWM interrupts.
*/
typedef enum
{
NRF_PWM_INT_STOPPED_MASK = PWM_INTENSET_STOPPED_Msk, ///< Interrupt on STOPPED event.
NRF_PWM_INT_SEQSTARTED0_MASK = PWM_INTENSET_SEQSTARTED0_Msk, ///< Interrupt on SEQSTARTED[0] event.
NRF_PWM_INT_SEQSTARTED1_MASK = PWM_INTENSET_SEQSTARTED1_Msk, ///< Interrupt on SEQSTARTED[1] event.
NRF_PWM_INT_SEQEND0_MASK = PWM_INTENSET_SEQEND0_Msk, ///< Interrupt on SEQEND[0] event.
NRF_PWM_INT_SEQEND1_MASK = PWM_INTENSET_SEQEND1_Msk, ///< Interrupt on SEQEND[1] event.
NRF_PWM_INT_PWMPERIODEND_MASK = PWM_INTENSET_PWMPERIODEND_Msk, ///< Interrupt on PWMPERIODEND event.
NRF_PWM_INT_LOOPSDONE_MASK = PWM_INTENSET_LOOPSDONE_Msk ///< Interrupt on LOOPSDONE event.
} nrf_pwm_int_mask_t;
/**
* @brief PWM shortcuts.
*/
typedef enum
{
NRF_PWM_SHORT_SEQEND0_STOP_MASK = PWM_SHORTS_SEQEND0_STOP_Msk, ///< Shortcut between SEQEND[0] event and STOP task.
NRF_PWM_SHORT_SEQEND1_STOP_MASK = PWM_SHORTS_SEQEND1_STOP_Msk, ///< Shortcut between SEQEND[1] event and STOP task.
NRF_PWM_SHORT_LOOPSDONE_SEQSTART0_MASK = PWM_SHORTS_LOOPSDONE_SEQSTART0_Msk, ///< Shortcut between LOOPSDONE event and SEQSTART[0] task.
NRF_PWM_SHORT_LOOPSDONE_SEQSTART1_MASK = PWM_SHORTS_LOOPSDONE_SEQSTART1_Msk, ///< Shortcut between LOOPSDONE event and SEQSTART[1] task.
NRF_PWM_SHORT_LOOPSDONE_STOP_MASK = PWM_SHORTS_LOOPSDONE_STOP_Msk ///< Shortcut between LOOPSDONE event and STOP task.
} nrf_pwm_short_mask_t;
/**
* @brief PWM modes of operation.
*/
typedef enum
{
NRF_PWM_MODE_UP = PWM_MODE_UPDOWN_Up, ///< Up counter (edge-aligned PWM duty cycle).
NRF_PWM_MODE_UP_AND_DOWN = PWM_MODE_UPDOWN_UpAndDown, ///< Up and down counter (center-aligned PWM duty cycle).
} nrf_pwm_mode_t;
/**
* @brief PWM base clock frequencies.
*/
typedef enum
{
NRF_PWM_CLK_16MHz = PWM_PRESCALER_PRESCALER_DIV_1, ///< 16 MHz / 1 = 16 MHz.
NRF_PWM_CLK_8MHz = PWM_PRESCALER_PRESCALER_DIV_2, ///< 16 MHz / 2 = 8 MHz.
NRF_PWM_CLK_4MHz = PWM_PRESCALER_PRESCALER_DIV_4, ///< 16 MHz / 4 = 4 MHz.
NRF_PWM_CLK_2MHz = PWM_PRESCALER_PRESCALER_DIV_8, ///< 16 MHz / 8 = 2 MHz.
NRF_PWM_CLK_1MHz = PWM_PRESCALER_PRESCALER_DIV_16, ///< 16 MHz / 16 = 1 MHz.
NRF_PWM_CLK_500kHz = PWM_PRESCALER_PRESCALER_DIV_32, ///< 16 MHz / 32 = 500 kHz.
NRF_PWM_CLK_250kHz = PWM_PRESCALER_PRESCALER_DIV_64, ///< 16 MHz / 64 = 250 kHz.
NRF_PWM_CLK_125kHz = PWM_PRESCALER_PRESCALER_DIV_128 ///< 16 MHz / 128 = 125 kHz.
} nrf_pwm_clk_t;
/**
* @brief PWM decoder load modes.
*
* The selected mode determines how the sequence data is read from RAM and
* spread to the compare registers.
*/
typedef enum
{
NRF_PWM_LOAD_COMMON = PWM_DECODER_LOAD_Common, ///< 1st half word (16-bit) used in all PWM channels (0-3).
NRF_PWM_LOAD_GROUPED = PWM_DECODER_LOAD_Grouped, ///< 1st half word (16-bit) used in channels 0 and 1; 2nd word in channels 2 and 3.
NRF_PWM_LOAD_INDIVIDUAL = PWM_DECODER_LOAD_Individual, ///< 1st half word (16-bit) used in channel 0; 2nd in channel 1; 3rd in channel 2; 4th in channel 3.
NRF_PWM_LOAD_WAVE_FORM = PWM_DECODER_LOAD_WaveForm ///< 1st half word (16-bit) used in channel 0; 2nd in channel 1; ... ; 4th as the top value for the pulse generator counter.
} nrf_pwm_dec_load_t;
/**
* @brief PWM decoder next step modes.
*
* The selected mode determines when the next value from the active sequence
* is loaded.
*/
typedef enum
{
NRF_PWM_STEP_AUTO = PWM_DECODER_MODE_RefreshCount, ///< Automatically after the current value is played and repeated the requested number of times.
NRF_PWM_STEP_TRIGGERED = PWM_DECODER_MODE_NextStep ///< When the @ref NRF_PWM_TASK_NEXTSTEP task is triggered.
} nrf_pwm_dec_step_t;
/**
* @brief Type used for defining duty cycle values for a sequence
* loaded in @ref NRF_PWM_LOAD_COMMON mode.
*/
typedef uint16_t nrf_pwm_values_common_t;
/**
* @brief Structure for defining duty cycle values for a sequence
* loaded in @ref NRF_PWM_LOAD_GROUPED mode.
*/
typedef struct {
uint16_t group_0; ///< Duty cycle value for group 0 (channels 0 and 1).
uint16_t group_1; ///< Duty cycle value for group 1 (channels 2 and 3).
} nrf_pwm_values_grouped_t;
/**
* @brief Structure for defining duty cycle values for a sequence
* loaded in @ref NRF_PWM_LOAD_INDIVIDUAL mode.
*/
typedef struct
{
uint16_t channel_0; ///< Duty cycle value for channel 0.
uint16_t channel_1; ///< Duty cycle value for channel 1.
uint16_t channel_2; ///< Duty cycle value for channel 2.
uint16_t channel_3; ///< Duty cycle value for channel 3.
} nrf_pwm_values_individual_t;
/**
* @brief Structure for defining duty cycle values for a sequence
* loaded in @ref NRF_PWM_LOAD_WAVE_FORM mode.
*/
typedef struct {
uint16_t channel_0; ///< Duty cycle value for channel 0.
uint16_t channel_1; ///< Duty cycle value for channel 1.
uint16_t channel_2; ///< Duty cycle value for channel 2.
uint16_t counter_top; ///< Top value for the pulse generator counter.
} nrf_pwm_values_wave_form_t;
/**
* @brief Union grouping pointers to arrays of duty cycle values applicable to
* various loading modes.
*/
typedef union {
nrf_pwm_values_common_t const * p_common; ///< Pointer to be used in @ref NRF_PWM_LOAD_COMMON mode.
nrf_pwm_values_grouped_t const * p_grouped; ///< Pointer to be used in @ref NRF_PWM_LOAD_GROUPED mode.
nrf_pwm_values_individual_t const * p_individual; ///< Pointer to be used in @ref NRF_PWM_LOAD_INDIVIDUAL mode.
nrf_pwm_values_wave_form_t const * p_wave_form; ///< Pointer to be used in @ref NRF_PWM_LOAD_WAVE_FORM mode.
uint16_t const * p_raw; ///< Pointer providing raw access to the values.
} nrf_pwm_values_t;
/**
* @brief Structure for defining a sequence of PWM duty cycles.
*
* When the sequence is set (by a call to @ref nrf_pwm_sequence_set), the
* provided duty cycle values are not copied. The @p values pointer is stored
* in the peripheral's internal register, and the values are loaded from RAM
* during the sequence playback. Therefore, you must ensure that the values
* do not change before and during the sequence playback (for example,
* the values cannot be placed in a local variable that is allocated on stack).
* If the sequence is played in a loop and the values should be updated
* before the next iteration, it is safe to modify them when the corresponding
* event signaling the end of sequence occurs (@ref NRF_PWM_EVENT_SEQEND0
* or @ref NRF_PWM_EVENT_SEQEND1, respectively).
*
* @note The @p repeats and @p end_delay values (which are written to the
* SEQ[n].REFRESH and SEQ[n].ENDDELAY registers in the peripheral,
* respectively) are ignored at the end of a complex sequence
* playback, indicated by the LOOPSDONE event.
* See the @linkProductSpecification52 for more information.
*/
typedef struct
{
nrf_pwm_values_t values; ///< Pointer to an array with duty cycle values. This array must be in Data RAM.
/**< This field is defined as an union of pointers
* to provide a convenient way to define duty
* cycle values in various loading modes
* (see @ref nrf_pwm_dec_load_t).
* In each value, the most significant bit (15)
* determines the polarity of the output and the
* others (14-0) compose the 15-bit value to be
* compared with the pulse generator counter. */
uint16_t length; ///< Number of 16-bit values in the array pointed by @p values.
uint32_t repeats; ///< Number of times that each duty cycle should be repeated (after being played once). Ignored in @ref NRF_PWM_STEP_TRIGGERED mode.
uint32_t end_delay; ///< Additional time (in PWM periods) that the last duty cycle is to be kept after the sequence is played. Ignored in @ref NRF_PWM_STEP_TRIGGERED mode.
} nrf_pwm_sequence_t;
/**
* @brief Helper macro for calculating the number of 16-bit values in specified
* array of duty cycle values.
*/
#define NRF_PWM_VALUES_LENGTH(array) (sizeof(array)/sizeof(uint16_t))
/**
* @brief Function for activating a specific PWM task.
*
* @param[in] p_pwm PWM instance.
* @param[in] task Task to activate.
*/
__STATIC_INLINE void nrf_pwm_task_trigger(NRF_PWM_Type * p_pwm,
nrf_pwm_task_t task);
/**
* @brief Function for getting the address of a specific PWM task register.
*
* @param[in] p_pwm PWM instance.
* @param[in] task Requested task.
*
* @return Address of the specified task register.
*/
__STATIC_INLINE uint32_t nrf_pwm_task_address_get(NRF_PWM_Type const * p_pwm,
nrf_pwm_task_t task);
/**
* @brief Function for clearing a specific PWM event.
*
* @param[in] p_pwm PWM instance.
* @param[in] event Event to clear.
*/
__STATIC_INLINE void nrf_pwm_event_clear(NRF_PWM_Type * p_pwm,
nrf_pwm_event_t event);
/**
* @brief Function for checking the state of a specific PWM event.
*
* @param[in] p_pwm PWM instance.
* @param[in] event Event to check.
*
* @retval true If the event is set.
* @retval false If the event is not set.
*/
__STATIC_INLINE bool nrf_pwm_event_check(NRF_PWM_Type const * p_pwm,
nrf_pwm_event_t event);
/**
* @brief Function for getting the address of a specific PWM event register.
*
* @param[in] p_pwm PWM instance.
* @param[in] event Requested event.
*
* @return Address of the specified event register.
*/
__STATIC_INLINE uint32_t nrf_pwm_event_address_get(NRF_PWM_Type const * p_pwm,
nrf_pwm_event_t event);
/**
* @brief Function for enabling specified shortcuts.
*
* @param[in] p_pwm PWM instance.
* @param[in] pwm_shorts_mask Shortcuts to enable.
*/
__STATIC_INLINE void nrf_pwm_shorts_enable(NRF_PWM_Type * p_pwm,
uint32_t pwm_shorts_mask);
/**
* @brief Function for disabling specified shortcuts.
*
* @param[in] p_pwm PWM instance.
* @param[in] pwm_shorts_mask Shortcuts to disable.
*/
__STATIC_INLINE void nrf_pwm_shorts_disable(NRF_PWM_Type * p_pwm,
uint32_t pwm_shorts_mask);
/**
* @brief Function for setting the configuration of PWM shortcuts.
*
* @param[in] p_pwm PWM instance.
* @param[in] pwm_shorts_mask Shortcuts configuration to set.
*/
__STATIC_INLINE void nrf_pwm_shorts_set(NRF_PWM_Type * p_pwm,
uint32_t pwm_shorts_mask);
/**
* @brief Function for enabling specified interrupts.
*
* @param[in] p_pwm PWM instance.
* @param[in] pwm_int_mask Interrupts to enable.
*/
__STATIC_INLINE void nrf_pwm_int_enable(NRF_PWM_Type * p_pwm,
uint32_t pwm_int_mask);
/**
* @brief Function for disabling specified interrupts.
*
* @param[in] p_pwm PWM instance.
* @param[in] pwm_int_mask Interrupts to disable.
*/
__STATIC_INLINE void nrf_pwm_int_disable(NRF_PWM_Type * p_pwm,
uint32_t pwm_int_mask);
/**
* @brief Function for setting the configuration of PWM interrupts.
*
* @param[in] p_pwm PWM instance.
* @param[in] pwm_int_mask Interrupts configuration to set.
*/
__STATIC_INLINE void nrf_pwm_int_set(NRF_PWM_Type * p_pwm,
uint32_t pwm_int_mask);
/**
* @brief Function for retrieving the state of a given interrupt.
*
* @param[in] p_pwm PWM instance.
* @param[in] pwm_int Interrupt to check.
*
* @retval true If the interrupt is enabled.
* @retval false If the interrupt is not enabled.
*/
__STATIC_INLINE bool nrf_pwm_int_enable_check(NRF_PWM_Type const * p_pwm,
nrf_pwm_int_mask_t pwm_int);
/**
* @brief Function for enabling the PWM peripheral.
*
* @param[in] p_pwm PWM instance.
*/
__STATIC_INLINE void nrf_pwm_enable(NRF_PWM_Type * p_pwm);
/**
* @brief Function for disabling the PWM peripheral.
*
* @param[in] p_pwm PWM instance.
*/
__STATIC_INLINE void nrf_pwm_disable(NRF_PWM_Type * p_pwm);
/**
* @brief Function for assigning pins to PWM output channels.
*
* Usage of all PWM output channels is optional. If a given channel is not
* needed, pass the @ref NRF_PWM_PIN_NOT_CONNECTED value instead of its pin
* number.
*
* @param[in] p_pwm PWM instance.
* @param[in] out_pins Array with pin numbers for individual PWM output channels.
*/
__STATIC_INLINE void nrf_pwm_pins_set(NRF_PWM_Type * p_pwm,
uint32_t out_pins[NRF_PWM_CHANNEL_COUNT]);
/**
* @brief Function for configuring the PWM peripheral.
*
* @param[in] p_pwm PWM instance.
* @param[in] base_clock Base clock frequency.
* @param[in] mode Operating mode of the pulse generator counter.
* @param[in] top_value Value up to which the pulse generator counter counts.
*/
__STATIC_INLINE void nrf_pwm_configure(NRF_PWM_Type * p_pwm,
nrf_pwm_clk_t base_clock,
nrf_pwm_mode_t mode,
uint16_t top_value);
/**
* @brief Function for defining a sequence of PWM duty cycles.
*
* @param[in] p_pwm PWM instance.
* @param[in] seq_id Identifier of the sequence (0 or 1).
* @param[in] p_seq Pointer to the sequence definition.
*/
__STATIC_INLINE void nrf_pwm_sequence_set(NRF_PWM_Type * p_pwm,
uint8_t seq_id,
nrf_pwm_sequence_t const * p_seq);
/**
* @brief Function for modifying the pointer to the duty cycle values
* in the specified sequence.
*
* @param[in] p_pwm PWM instance.
* @param[in] seq_id Identifier of the sequence (0 or 1).
* @param[in] p_values Pointer to an array with duty cycle values.
*/
__STATIC_INLINE void nrf_pwm_seq_ptr_set(NRF_PWM_Type * p_pwm,
uint8_t seq_id,
uint16_t const * p_values);
/**
* @brief Function for modifying the total number of duty cycle values
* in the specified sequence.
*
* @param[in] p_pwm PWM instance.
* @param[in] seq_id Identifier of the sequence (0 or 1).
* @param[in] length Number of duty cycle values.
*/
__STATIC_INLINE void nrf_pwm_seq_cnt_set(NRF_PWM_Type * p_pwm,
uint8_t seq_id,
uint16_t length);
/**
* @brief Function for modifying the additional number of PWM periods spent
* on each duty cycle value in the specified sequence.
*
* @param[in] p_pwm PWM instance.
* @param[in] seq_id Identifier of the sequence (0 or 1).
* @param[in] refresh Number of additional PWM periods for each duty cycle value.
*/
__STATIC_INLINE void nrf_pwm_seq_refresh_set(NRF_PWM_Type * p_pwm,
uint8_t seq_id,
uint32_t refresh);
/**
* @brief Function for modifying the additional time added after the sequence
* is played.
*
* @param[in] p_pwm PWM instance.
* @param[in] seq_id Identifier of the sequence (0 or 1).
* @param[in] end_delay Number of PWM periods added at the end of the sequence.
*/
__STATIC_INLINE void nrf_pwm_seq_end_delay_set(NRF_PWM_Type * p_pwm,
uint8_t seq_id,
uint32_t end_delay);
/**
* @brief Function for setting the mode of loading sequence data from RAM
* and advancing the sequence.
*
* @param[in] p_pwm PWM instance.
* @param[in] dec_load Mode of loading sequence data from RAM.
* @param[in] dec_step Mode of advancing the active sequence.
*/
__STATIC_INLINE void nrf_pwm_decoder_set(NRF_PWM_Type * p_pwm,
nrf_pwm_dec_load_t dec_load,
nrf_pwm_dec_step_t dec_step);
/**
* @brief Function for setting the number of times the sequence playback
* should be performed.
*
* This function applies to two-sequence playback (concatenated sequence 0 and 1).
* A single sequence can be played back only once.
*
* @param[in] p_pwm PWM instance.
* @param[in] loop_count Number of times to perform the sequence playback.
*/
__STATIC_INLINE void nrf_pwm_loop_set(NRF_PWM_Type * p_pwm,
uint16_t loop_count);
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE void nrf_pwm_task_trigger(NRF_PWM_Type * p_pwm,
nrf_pwm_task_t task)
{
*((volatile uint32_t *)((uint8_t *)p_pwm + (uint32_t)task)) = 0x1UL;
}
__STATIC_INLINE uint32_t nrf_pwm_task_address_get(NRF_PWM_Type const * p_pwm,
nrf_pwm_task_t task)
{
return ((uint32_t)p_pwm + (uint32_t)task);
}
__STATIC_INLINE void nrf_pwm_event_clear(NRF_PWM_Type * p_pwm,
nrf_pwm_event_t event)
{
*((volatile uint32_t *)((uint8_t *)p_pwm + (uint32_t)event)) = 0x0UL;
}
__STATIC_INLINE bool nrf_pwm_event_check(NRF_PWM_Type const * p_pwm,
nrf_pwm_event_t event)
{
return (bool)*(volatile uint32_t *)((uint8_t *)p_pwm + (uint32_t)event);
}
__STATIC_INLINE uint32_t nrf_pwm_event_address_get(NRF_PWM_Type const * p_pwm,
nrf_pwm_event_t event)
{
return ((uint32_t)p_pwm + (uint32_t)event);
}
__STATIC_INLINE void nrf_pwm_shorts_enable(NRF_PWM_Type * p_pwm,
uint32_t pwm_shorts_mask)
{
p_pwm->SHORTS |= pwm_shorts_mask;
}
__STATIC_INLINE void nrf_pwm_shorts_disable(NRF_PWM_Type * p_pwm,
uint32_t pwm_shorts_mask)
{
p_pwm->SHORTS &= ~(pwm_shorts_mask);
}
__STATIC_INLINE void nrf_pwm_shorts_set(NRF_PWM_Type * p_pwm,
uint32_t pwm_shorts_mask)
{
p_pwm->SHORTS = pwm_shorts_mask;
}
__STATIC_INLINE void nrf_pwm_int_enable(NRF_PWM_Type * p_pwm,
uint32_t pwm_int_mask)
{
p_pwm->INTENSET = pwm_int_mask;
}
__STATIC_INLINE void nrf_pwm_int_disable(NRF_PWM_Type * p_pwm,
uint32_t pwm_int_mask)
{
p_pwm->INTENCLR = pwm_int_mask;
}
__STATIC_INLINE void nrf_pwm_int_set(NRF_PWM_Type * p_pwm,
uint32_t pwm_int_mask)
{
p_pwm->INTEN = pwm_int_mask;
}
__STATIC_INLINE bool nrf_pwm_int_enable_check(NRF_PWM_Type const * p_pwm,
nrf_pwm_int_mask_t pwm_int)
{
return (bool)(p_pwm->INTENSET & pwm_int);
}
__STATIC_INLINE void nrf_pwm_enable(NRF_PWM_Type * p_pwm)
{
p_pwm->ENABLE = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos);
}
__STATIC_INLINE void nrf_pwm_disable(NRF_PWM_Type * p_pwm)
{
p_pwm->ENABLE = (PWM_ENABLE_ENABLE_Disabled << PWM_ENABLE_ENABLE_Pos);
}
__STATIC_INLINE void nrf_pwm_pins_set(NRF_PWM_Type * p_pwm,
uint32_t out_pins[NRF_PWM_CHANNEL_COUNT])
{
uint8_t i;
for (i = 0; i < NRF_PWM_CHANNEL_COUNT; ++i)
{
p_pwm->PSEL.OUT[i] = out_pins[i];
}
}
__STATIC_INLINE void nrf_pwm_configure(NRF_PWM_Type * p_pwm,
nrf_pwm_clk_t base_clock,
nrf_pwm_mode_t mode,
uint16_t top_value)
{
ASSERT(top_value <= PWM_COUNTERTOP_COUNTERTOP_Msk);
p_pwm->PRESCALER = base_clock;
p_pwm->MODE = mode;
p_pwm->COUNTERTOP = top_value;
}
__STATIC_INLINE void nrf_pwm_sequence_set(NRF_PWM_Type * p_pwm,
uint8_t seq_id,
nrf_pwm_sequence_t const * p_seq)
{
ASSERT(p_seq != NULL);
nrf_pwm_seq_ptr_set( p_pwm, seq_id, p_seq->values.p_raw);
nrf_pwm_seq_cnt_set( p_pwm, seq_id, p_seq->length);
nrf_pwm_seq_refresh_set( p_pwm, seq_id, p_seq->repeats);
nrf_pwm_seq_end_delay_set(p_pwm, seq_id, p_seq->end_delay);
}
__STATIC_INLINE void nrf_pwm_seq_ptr_set(NRF_PWM_Type * p_pwm,
uint8_t seq_id,
uint16_t const * p_values)
{
ASSERT(seq_id <= 1);
ASSERT(p_values != NULL);
p_pwm->SEQ[seq_id].PTR = (uint32_t)p_values;
}
__STATIC_INLINE void nrf_pwm_seq_cnt_set(NRF_PWM_Type * p_pwm,
uint8_t seq_id,
uint16_t length)
{
ASSERT(seq_id <= 1);
ASSERT(length != 0);
ASSERT(length <= PWM_SEQ_CNT_CNT_Msk);
p_pwm->SEQ[seq_id].CNT = length;
}
__STATIC_INLINE void nrf_pwm_seq_refresh_set(NRF_PWM_Type * p_pwm,
uint8_t seq_id,
uint32_t refresh)
{
ASSERT(seq_id <= 1);
ASSERT(refresh <= PWM_SEQ_REFRESH_CNT_Msk);
p_pwm->SEQ[seq_id].REFRESH = refresh;
}
__STATIC_INLINE void nrf_pwm_seq_end_delay_set(NRF_PWM_Type * p_pwm,
uint8_t seq_id,
uint32_t end_delay)
{
ASSERT(seq_id <= 1);
ASSERT(end_delay <= PWM_SEQ_ENDDELAY_CNT_Msk);
p_pwm->SEQ[seq_id].ENDDELAY = end_delay;
}
__STATIC_INLINE void nrf_pwm_decoder_set(NRF_PWM_Type * p_pwm,
nrf_pwm_dec_load_t dec_load,
nrf_pwm_dec_step_t dec_step)
{
p_pwm->DECODER = ((uint32_t)dec_load << PWM_DECODER_LOAD_Pos) |
((uint32_t)dec_step << PWM_DECODER_MODE_Pos);
}
__STATIC_INLINE void nrf_pwm_loop_set(NRF_PWM_Type * p_pwm,
uint16_t loop_count)
{
p_pwm->LOOP = loop_count;
}
#endif // SUPPRESS_INLINE_IMPLEMENTATION
#endif // NRF52
#endif // NRF_PWM_H__
/** @} */

View File

@ -1,281 +0,0 @@
/*
* Copyright (c) 2014 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 RNG HAL API.
*/
#ifndef NRF_RNG_H__
#define NRF_RNG_H__
/**
* @defgroup nrf_rng_hal RNG HAL
* @{
* @ingroup nrf_rng
* @brief Hardware access layer for managing the random number generator (RNG).
*/
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "nrf.h"
#ifdef __cplusplus
extern "C" {
#endif
#define NRF_RNG_TASK_SET (1UL)
#define NRF_RNG_EVENT_CLEAR (0UL)
/**
* @enum nrf_rng_task_t
* @brief RNG tasks.
*/
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
{
NRF_RNG_TASK_START = offsetof(NRF_RNG_Type, TASKS_START), /**< Start the random number generator. */
NRF_RNG_TASK_STOP = offsetof(NRF_RNG_Type, TASKS_STOP) /**< Stop the random number generator. */
} nrf_rng_task_t; /*lint -restore */
/**
* @enum nrf_rng_event_t
* @brief RNG events.
*/
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
{
NRF_RNG_EVENT_VALRDY = offsetof(NRF_RNG_Type, EVENTS_VALRDY) /**< New random number generated event. */
} nrf_rng_event_t; /*lint -restore */
/**
* @enum nrf_rng_int_mask_t
* @brief RNG interrupts.
*/
typedef enum
{
NRF_RNG_INT_VALRDY_MASK = RNG_INTENSET_VALRDY_Msk /**< Mask for enabling or disabling an interrupt on VALRDY event. */
} nrf_rng_int_mask_t;
/**
* @enum nrf_rng_short_mask_t
* @brief Types of RNG shortcuts.
*/
typedef enum
{
NRF_RNG_SHORT_VALRDY_STOP_MASK = RNG_SHORTS_VALRDY_STOP_Msk /**< Mask for setting shortcut between EVENT_VALRDY and TASK_STOP. */
} nrf_rng_short_mask_t;
/**
* @brief Function for enabling interrupts.
*
* @param[in] rng_int_mask Mask of interrupts.
*/
__STATIC_INLINE void nrf_rng_int_enable(uint32_t rng_int_mask);
/**
* @brief Function for disabling interrupts.
*
* @param[in] rng_int_mask Mask of interrupts.
*/
__STATIC_INLINE void nrf_rng_int_disable(uint32_t rng_int_mask);
/**
* @brief Function for getting the state of a specific interrupt.
*
* @param[in] rng_int_mask Interrupt.
*
* @retval true If the interrupt is not enabled.
* @retval false If the interrupt is enabled.
*/
__STATIC_INLINE bool nrf_rng_int_get(nrf_rng_int_mask_t rng_int_mask);
/**
* @brief Function for getting the address of a specific task.
*
* This function can be used by the PPI module.
*
* @param[in] rng_task Task.
*/
__STATIC_INLINE uint32_t * nrf_rng_task_address_get(nrf_rng_task_t rng_task);
/**
* @brief Function for setting a specific task.
*
* @param[in] rng_task Task.
*/
__STATIC_INLINE void nrf_rng_task_trigger(nrf_rng_task_t rng_task);
/**
* @brief Function for getting address of a specific event.
*
* This function can be used by the PPI module.
*
* @param[in] rng_event Event.
*/
__STATIC_INLINE uint32_t * nrf_rng_event_address_get(nrf_rng_event_t rng_event);
/**
* @brief Function for clearing a specific event.
*
* @param[in] rng_event Event.
*/
__STATIC_INLINE void nrf_rng_event_clear(nrf_rng_event_t rng_event);
/**
* @brief Function for getting the state of a specific event.
*
* @param[in] rng_event Event.
*
* @retval true If the event is not set.
* @retval false If the event is set.
*/
__STATIC_INLINE bool nrf_rng_event_get(nrf_rng_event_t rng_event);
/**
* @brief Function for setting shortcuts.
*
* @param[in] rng_short_mask Mask of shortcuts.
*
*/
__STATIC_INLINE void nrf_rng_shorts_enable(uint32_t rng_short_mask);
/**
* @brief Function for clearing shortcuts.
*
* @param[in] rng_short_mask Mask of shortcuts.
*
*/
__STATIC_INLINE void nrf_rng_shorts_disable(uint32_t rng_short_mask);
/**
* @brief Function for getting the previously generated random value.
*
* @return Previously generated random value.
*/
__STATIC_INLINE uint8_t nrf_rng_random_value_get(void);
/**
* @brief Function for enabling digital error correction.
*/
__STATIC_INLINE void nrf_rng_error_correction_enable(void);
/**
* @brief Function for disabling digital error correction.
*/
__STATIC_INLINE void nrf_rng_error_correction_disable(void);
/**
*@}
**/
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE void nrf_rng_int_enable(uint32_t rng_int_mask)
{
NRF_RNG->INTENSET = rng_int_mask;
}
__STATIC_INLINE void nrf_rng_int_disable(uint32_t rng_int_mask)
{
NRF_RNG->INTENCLR = rng_int_mask;
}
__STATIC_INLINE bool nrf_rng_int_get(nrf_rng_int_mask_t rng_int_mask)
{
return (bool)(NRF_RNG->INTENCLR & rng_int_mask);
}
__STATIC_INLINE uint32_t * nrf_rng_task_address_get(nrf_rng_task_t rng_task)
{
return (uint32_t *)((uint8_t *)NRF_RNG + rng_task);
}
__STATIC_INLINE void nrf_rng_task_trigger(nrf_rng_task_t rng_task)
{
*((volatile uint32_t *)((uint8_t *)NRF_RNG + rng_task)) = NRF_RNG_TASK_SET;
}
__STATIC_INLINE uint32_t * nrf_rng_event_address_get(nrf_rng_event_t rng_event)
{
return (uint32_t *)((uint8_t *)NRF_RNG + rng_event);
}
__STATIC_INLINE void nrf_rng_event_clear(nrf_rng_event_t rng_event)
{
*((volatile uint32_t *)((uint8_t *)NRF_RNG + rng_event)) = NRF_RNG_EVENT_CLEAR;
#if __CORTEX_M == 0x04
volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)NRF_RNG + rng_event));
(void)dummy;
#endif
}
__STATIC_INLINE bool nrf_rng_event_get(nrf_rng_event_t rng_event)
{
return (bool) * ((volatile uint32_t *)((uint8_t *)NRF_RNG + rng_event));
}
__STATIC_INLINE void nrf_rng_shorts_enable(uint32_t rng_short_mask)
{
NRF_RNG->SHORTS |= rng_short_mask;
}
__STATIC_INLINE void nrf_rng_shorts_disable(uint32_t rng_short_mask)
{
NRF_RNG->SHORTS &= ~rng_short_mask;
}
__STATIC_INLINE uint8_t nrf_rng_random_value_get(void)
{
return (uint8_t)(NRF_RNG->VALUE & RNG_VALUE_VALUE_Msk);
}
__STATIC_INLINE void nrf_rng_error_correction_enable(void)
{
NRF_RNG->CONFIG |= RNG_CONFIG_DERCEN_Msk;
}
__STATIC_INLINE void nrf_rng_error_correction_disable(void)
{
NRF_RNG->CONFIG &= ~RNG_CONFIG_DERCEN_Msk;
}
#endif
#ifdef __cplusplus
}
#endif
#endif /* NRF_RNG_H__ */

View File

@ -1,331 +0,0 @@
/*
* Copyright (c) 2014 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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 RTC HAL API.
*/
#ifndef NRF_RTC_H
#define NRF_RTC_H
/**
* @defgroup nrf_rtc_hal RTC HAL
* @{
* @ingroup nrf_rtc
* @brief Hardware access layer for managing the real time counter (RTC).
*/
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "nrf.h"
#include "nrf_assert.h"
/**
* @brief Macro for getting the number of compare channels available
* in a given RTC instance.
*/
#ifdef NRF51
#define NRF_RTC_CC_CHANNEL_COUNT(id) 4
#else
#define NRF_RTC_CC_CHANNEL_COUNT(id) ((id) == 0 ? 3 : 4)
#endif
#define RTC_INPUT_FREQ 32768 /**< Input frequency of the RTC instance. */
/**< Macro for wrapping values to RTC capacity. */
#define RTC_WRAP(val) (val & RTC_COUNTER_COUNTER_Msk)
#define RTC_CHANNEL_INT_MASK(ch) ((uint32_t)NRF_RTC_INT_COMPARE0_MASK << ch)
#define RTC_CHANNEL_EVENT_ADDR(ch) (nrf_rtc_event_t)(NRF_RTC_EVENT_COMPARE_0 + ch*sizeof(uint32_t))
/**
* @enum nrf_rtc_task_t
* @brief RTC tasks.
*/
typedef enum
{
/*lint -save -e30*/
NRF_RTC_TASK_START = offsetof(NRF_RTC_Type,TASKS_START), /**< Start. */
NRF_RTC_TASK_STOP = offsetof(NRF_RTC_Type,TASKS_STOP), /**< Stop. */
NRF_RTC_TASK_CLEAR = offsetof(NRF_RTC_Type,TASKS_CLEAR), /**< Clear. */
NRF_RTC_TASK_TRIGGER_OVERFLOW = offsetof(NRF_RTC_Type,TASKS_TRIGOVRFLW),/**< Trigger overflow. */
/*lint -restore*/
} nrf_rtc_task_t;
/**
* @enum nrf_rtc_event_t
* @brief RTC events.
*/
typedef enum
{
/*lint -save -e30*/
NRF_RTC_EVENT_TICK = offsetof(NRF_RTC_Type,EVENTS_TICK), /**< Tick event. */
NRF_RTC_EVENT_OVERFLOW = offsetof(NRF_RTC_Type,EVENTS_OVRFLW), /**< Overflow event. */
NRF_RTC_EVENT_COMPARE_0 = offsetof(NRF_RTC_Type,EVENTS_COMPARE[0]), /**< Compare 0 event. */
NRF_RTC_EVENT_COMPARE_1 = offsetof(NRF_RTC_Type,EVENTS_COMPARE[1]), /**< Compare 1 event. */
NRF_RTC_EVENT_COMPARE_2 = offsetof(NRF_RTC_Type,EVENTS_COMPARE[2]), /**< Compare 2 event. */
NRF_RTC_EVENT_COMPARE_3 = offsetof(NRF_RTC_Type,EVENTS_COMPARE[3]) /**< Compare 3 event. */
/*lint -restore*/
} nrf_rtc_event_t;
/**
* @enum nrf_rtc_int_t
* @brief RTC interrupts.
*/
typedef enum
{
NRF_RTC_INT_TICK_MASK = RTC_INTENSET_TICK_Msk, /**< RTC interrupt from tick event. */
NRF_RTC_INT_OVERFLOW_MASK = RTC_INTENSET_OVRFLW_Msk, /**< RTC interrupt from overflow event. */
NRF_RTC_INT_COMPARE0_MASK = RTC_INTENSET_COMPARE0_Msk, /**< RTC interrupt from compare event on channel 0. */
NRF_RTC_INT_COMPARE1_MASK = RTC_INTENSET_COMPARE1_Msk, /**< RTC interrupt from compare event on channel 1. */
NRF_RTC_INT_COMPARE2_MASK = RTC_INTENSET_COMPARE2_Msk, /**< RTC interrupt from compare event on channel 2. */
NRF_RTC_INT_COMPARE3_MASK = RTC_INTENSET_COMPARE3_Msk /**< RTC interrupt from compare event on channel 3. */
} nrf_rtc_int_t;
/**@brief Function for setting a compare value for a channel.
*
* @param[in] p_rtc Pointer to the instance register structure.
* @param[in] ch Channel.
* @param[in] cc_val Compare value to set.
*/
__STATIC_INLINE void nrf_rtc_cc_set(NRF_RTC_Type * p_rtc, uint32_t ch, uint32_t cc_val);
/**@brief Function for returning the compare value for a channel.
*
* @param[in] p_rtc Pointer to the instance register structure.
* @param[in] ch Channel.
*
* @return COMPARE[ch] value.
*/
__STATIC_INLINE uint32_t nrf_rtc_cc_get(NRF_RTC_Type * p_rtc, uint32_t ch);
/**@brief Function for enabling interrupts.
*
* @param[in] p_rtc Pointer to the instance register structure.
* @param[in] mask Interrupt mask to be enabled.
*/
__STATIC_INLINE void nrf_rtc_int_enable(NRF_RTC_Type * p_rtc, uint32_t mask);
/**@brief Function for disabling interrupts.
*
* @param[in] p_rtc Pointer to the instance register structure.
* @param[in] mask Interrupt mask to be disabled.
*/
__STATIC_INLINE void nrf_rtc_int_disable(NRF_RTC_Type * p_rtc, uint32_t mask);
/**@brief Function for checking if interrupts are enabled.
*
* @param[in] p_rtc Pointer to the instance register structure.
* @param[in] mask Mask of interrupt flags to check.
*
* @return Mask with enabled interrupts.
*/
__STATIC_INLINE uint32_t nrf_rtc_int_is_enabled(NRF_RTC_Type * p_rtc, uint32_t mask);
/**@brief Function for returning the status of currently enabled interrupts.
*
* @param[in] p_rtc Pointer to the instance register structure.
*
* @return Value in INTEN register.
*/
__STATIC_INLINE uint32_t nrf_rtc_int_get(NRF_RTC_Type * p_rtc);
/**@brief Function for checking if an event is pending.
*
* @param[in] p_rtc Pointer to the instance register structure.
* @param[in] event Address of the event.
*
* @return Mask of pending events.
*/
__STATIC_INLINE uint32_t nrf_rtc_event_pending(NRF_RTC_Type * p_rtc, nrf_rtc_event_t event);
/**@brief Function for clearing an event.
*
* @param[in] p_rtc Pointer to the instance register structure.
* @param[in] event Event to clear.
*/
__STATIC_INLINE void nrf_rtc_event_clear(NRF_RTC_Type * p_rtc, nrf_rtc_event_t event);
/**@brief Function for returning a counter value.
*
* @param[in] p_rtc Pointer to the instance register structure.
*
* @return Counter value.
*/
__STATIC_INLINE uint32_t nrf_rtc_counter_get(NRF_RTC_Type * p_rtc);
/**@brief Function for setting a prescaler value.
*
* @param[in] p_rtc Pointer to the instance register structure.
* @param[in] val Value to set the prescaler to.
*/
__STATIC_INLINE void nrf_rtc_prescaler_set(NRF_RTC_Type * p_rtc, uint32_t val);
/**@brief Function for returning the address of an event.
*
* @param[in] p_rtc Pointer to the instance register structure.
* @param[in] event Requested event.
*
* @return Address of the requested event register.
*/
__STATIC_INLINE uint32_t nrf_rtc_event_address_get(NRF_RTC_Type * p_rtc, nrf_rtc_event_t event);
/**@brief Function for returning the address of a task.
*
* @param[in] p_rtc Pointer to the instance register structure.
* @param[in] task Requested task.
*
* @return Address of the requested task register.
*/
__STATIC_INLINE uint32_t nrf_rtc_task_address_get(NRF_RTC_Type * p_rtc, nrf_rtc_task_t task);
/**@brief Function for starting a task.
*
* @param[in] p_rtc Pointer to the instance register structure.
* @param[in] task Requested task.
*/
__STATIC_INLINE void nrf_rtc_task_trigger(NRF_RTC_Type * p_rtc, nrf_rtc_task_t task);
/**@brief Function for enabling events.
*
* @param[in] p_rtc Pointer to the instance register structure.
* @param[in] mask Mask of event flags to enable.
*/
__STATIC_INLINE void nrf_rtc_event_enable(NRF_RTC_Type * p_rtc, uint32_t mask);
/**@brief Function for disabling an event.
*
* @param[in] p_rtc Pointer to the instance register structure.
* @param[in] event Requested event.
*/
__STATIC_INLINE void nrf_rtc_event_disable(NRF_RTC_Type * p_rtc, uint32_t event);
/**
*@}
**/
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE void nrf_rtc_cc_set(NRF_RTC_Type * p_rtc, uint32_t ch, uint32_t cc_val)
{
p_rtc->CC[ch] = cc_val;
}
__STATIC_INLINE uint32_t nrf_rtc_cc_get(NRF_RTC_Type * p_rtc, uint32_t ch)
{
return p_rtc->CC[ch];
}
__STATIC_INLINE void nrf_rtc_int_enable(NRF_RTC_Type * p_rtc, uint32_t mask)
{
p_rtc->INTENSET = mask;
}
__STATIC_INLINE void nrf_rtc_int_disable(NRF_RTC_Type * p_rtc, uint32_t mask)
{
p_rtc->INTENCLR = mask;
}
__STATIC_INLINE uint32_t nrf_rtc_int_is_enabled(NRF_RTC_Type * p_rtc, uint32_t mask)
{
return (p_rtc->INTENSET & mask);
}
__STATIC_INLINE uint32_t nrf_rtc_int_get(NRF_RTC_Type * p_rtc)
{
return p_rtc->INTENSET;
}
__STATIC_INLINE uint32_t nrf_rtc_event_pending(NRF_RTC_Type * p_rtc, nrf_rtc_event_t event)
{
return *(volatile uint32_t *)((uint8_t *)p_rtc + (uint32_t)event);
}
__STATIC_INLINE void nrf_rtc_event_clear(NRF_RTC_Type * p_rtc, nrf_rtc_event_t event)
{
*((volatile uint32_t *)((uint8_t *)p_rtc + (uint32_t)event)) = 0;
#if __CORTEX_M == 0x04
volatile uint32_t dummy = *((volatile uint32_t *)((uint8_t *)p_rtc + (uint32_t)event));
(void)dummy;
#endif
}
__STATIC_INLINE uint32_t nrf_rtc_counter_get(NRF_RTC_Type * p_rtc)
{
return p_rtc->COUNTER;
}
__STATIC_INLINE void nrf_rtc_prescaler_set(NRF_RTC_Type * p_rtc, uint32_t val)
{
ASSERT(val <= (RTC_PRESCALER_PRESCALER_Msk >> RTC_PRESCALER_PRESCALER_Pos));
p_rtc->PRESCALER = val;
}
__STATIC_INLINE uint32_t rtc_prescaler_get(NRF_RTC_Type * p_rtc)
{
return p_rtc->PRESCALER;
}
__STATIC_INLINE uint32_t nrf_rtc_event_address_get(NRF_RTC_Type * p_rtc, nrf_rtc_event_t event)
{
return (uint32_t)p_rtc + event;
}
__STATIC_INLINE uint32_t nrf_rtc_task_address_get(NRF_RTC_Type * p_rtc, nrf_rtc_task_t task)
{
return (uint32_t)p_rtc + task;
}
__STATIC_INLINE void nrf_rtc_task_trigger(NRF_RTC_Type * p_rtc, nrf_rtc_task_t task)
{
*(__IO uint32_t *)((uint32_t)p_rtc + task) = 1;
}
__STATIC_INLINE void nrf_rtc_event_enable(NRF_RTC_Type * p_rtc, uint32_t mask)
{
p_rtc->EVTENSET = mask;
}
__STATIC_INLINE void nrf_rtc_event_disable(NRF_RTC_Type * p_rtc, uint32_t mask)
{
p_rtc->EVTENCLR = mask;
}
#endif
#endif /* NRF_RTC_H */

View File

@ -1,62 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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.
*
*/
#ifdef NRF52
/**
* @file
* @brief SAADC HAL implementation
*/
#include "nrf_saadc.h"
void nrf_saadc_channel_init(uint8_t channel, nrf_saadc_channel_config_t const * const config)
{
NRF_SAADC->CH[channel].CONFIG =
((config->resistor_p << SAADC_CH_CONFIG_RESP_Pos) & SAADC_CH_CONFIG_RESP_Msk)
| ((config->resistor_n << SAADC_CH_CONFIG_RESN_Pos) & SAADC_CH_CONFIG_RESN_Msk)
| ((config->gain << SAADC_CH_CONFIG_GAIN_Pos) & SAADC_CH_CONFIG_GAIN_Msk)
| ((config->reference << SAADC_CH_CONFIG_REFSEL_Pos) & SAADC_CH_CONFIG_REFSEL_Msk)
| ((config->acq_time << SAADC_CH_CONFIG_TACQ_Pos) & SAADC_CH_CONFIG_TACQ_Msk)
| ((config->mode << SAADC_CH_CONFIG_MODE_Pos) & SAADC_CH_CONFIG_MODE_Msk);
nrf_saadc_channel_input_set(channel, config->pin_p, config->pin_n);
return;
}
#endif //NRF52

View File

@ -1,587 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_SAADC_H_
#define NRF_SAADC_H_
#ifdef NRF52
/**
* @defgroup nrf_saadc_hal SAADC HAL
* @{
* @ingroup nrf_saadc
*
* @brief @tagAPI52 Hardware access layer for accessing the SAADC peripheral.
*/
#include <stdbool.h>
#include <stddef.h>
#include "nrf.h"
#include "nrf_assert.h"
#define NRF_SAADC_CHANNEL_COUNT 8
/**
* @brief Resolution of the analog-to-digital converter.
*/
typedef enum
{
NRF_SAADC_RESOLUTION_8BIT = SAADC_RESOLUTION_VAL_8bit, ///< 8 bit resolution.
NRF_SAADC_RESOLUTION_10BIT = SAADC_RESOLUTION_VAL_10bit, ///< 10 bit resolution.
NRF_SAADC_RESOLUTION_12BIT = SAADC_RESOLUTION_VAL_12bit, ///< 12 bit resolution.
NRF_SAADC_RESOLUTION_14BIT = SAADC_RESOLUTION_VAL_14bit ///< 14 bit resolution.
} nrf_saadc_resolution_t;
/**
* @brief Input selection for the analog-to-digital converter.
*/
typedef enum
{
NRF_SAADC_INPUT_DISABLED = SAADC_CH_PSELP_PSELP_NC, ///< Not connected.
NRF_SAADC_INPUT_AIN0 = SAADC_CH_PSELP_PSELP_AnalogInput0, ///< Analog input 0 (AIN0).
NRF_SAADC_INPUT_AIN1 = SAADC_CH_PSELP_PSELP_AnalogInput1, ///< Analog input 1 (AIN1).
NRF_SAADC_INPUT_AIN2 = SAADC_CH_PSELP_PSELP_AnalogInput2, ///< Analog input 2 (AIN2).
NRF_SAADC_INPUT_AIN3 = SAADC_CH_PSELP_PSELP_AnalogInput3, ///< Analog input 3 (AIN3).
NRF_SAADC_INPUT_AIN4 = SAADC_CH_PSELP_PSELP_AnalogInput4, ///< Analog input 4 (AIN4).
NRF_SAADC_INPUT_AIN5 = SAADC_CH_PSELP_PSELP_AnalogInput5, ///< Analog input 5 (AIN5).
NRF_SAADC_INPUT_AIN6 = SAADC_CH_PSELP_PSELP_AnalogInput6, ///< Analog input 6 (AIN6).
NRF_SAADC_INPUT_AIN7 = SAADC_CH_PSELP_PSELP_AnalogInput7, ///< Analog input 7 (AIN7).
NRF_SAADC_INPUT_VDD = SAADC_CH_PSELP_PSELP_VDD ///< VDD as input.
} nrf_saadc_input_t;
/**
* @brief Analog-to-digital converter oversampling mode.
*/
typedef enum
{
NRF_SAADC_OVERSAMPLE_DISABLED = SAADC_OVERSAMPLE_OVERSAMPLE_Bypass, ///< No oversampling.
NRF_SAADC_OVERSAMPLE_2X = SAADC_OVERSAMPLE_OVERSAMPLE_Over2x, ///< Oversample 2x.
NRF_SAADC_OVERSAMPLE_4X = SAADC_OVERSAMPLE_OVERSAMPLE_Over4x, ///< Oversample 4x.
NRF_SAADC_OVERSAMPLE_8X = SAADC_OVERSAMPLE_OVERSAMPLE_Over8x, ///< Oversample 8x.
NRF_SAADC_OVERSAMPLE_16X = SAADC_OVERSAMPLE_OVERSAMPLE_Over16x, ///< Oversample 16x.
NRF_SAADC_OVERSAMPLE_32X = SAADC_OVERSAMPLE_OVERSAMPLE_Over32x, ///< Oversample 32x.
NRF_SAADC_OVERSAMPLE_64X = SAADC_OVERSAMPLE_OVERSAMPLE_Over64x, ///< Oversample 64x.
NRF_SAADC_OVERSAMPLE_128X = SAADC_OVERSAMPLE_OVERSAMPLE_Over128x, ///< Oversample 128x.
NRF_SAADC_OVERSAMPLE_256X = SAADC_OVERSAMPLE_OVERSAMPLE_Over256x ///< Oversample 256x.
} nrf_saadc_oversample_t;
/**
* @brief Analog-to-digital converter channel resistor control.
*/
typedef enum
{
NRF_SAADC_RESISTOR_DISABLED = SAADC_CH_CONFIG_RESP_Bypass, ///< Bypass resistor ladder.
NRF_SAADC_RESISTOR_PULLDOWN = SAADC_CH_CONFIG_RESP_Pulldown, ///< Pull-down to GND.
NRF_SAADC_RESISTOR_PULLUP = SAADC_CH_CONFIG_RESP_Pullup, ///< Pull-up to VDD.
NRF_SAADC_RESISTOR_VDD1_2 = SAADC_CH_CONFIG_RESP_VDD1_2 ///< Set input at VDD/2.
} nrf_saadc_resistor_t;
/**
* @brief Gain factor of the analog-to-digital converter input.
*/
typedef enum
{
NRF_SAADC_GAIN1_6 = SAADC_CH_CONFIG_GAIN_Gain1_6, ///< Gain factor 1/6.
NRF_SAADC_GAIN1_5 = SAADC_CH_CONFIG_GAIN_Gain1_5, ///< Gain factor 1/5.
NRF_SAADC_GAIN1_4 = SAADC_CH_CONFIG_GAIN_Gain1_4, ///< Gain factor 1/4.
NRF_SAADC_GAIN1_3 = SAADC_CH_CONFIG_GAIN_Gain1_3, ///< Gain factor 1/3.
NRF_SAADC_GAIN1_2 = SAADC_CH_CONFIG_GAIN_Gain1_2, ///< Gain factor 1/2.
NRF_SAADC_GAIN1 = SAADC_CH_CONFIG_GAIN_Gain1, ///< Gain factor 1.
NRF_SAADC_GAIN2 = SAADC_CH_CONFIG_GAIN_Gain2, ///< Gain factor 2.
NRF_SAADC_GAIN4 = SAADC_CH_CONFIG_GAIN_Gain4, ///< Gain factor 4.
} nrf_saadc_gain_t;
/**
* @brief Reference selection for the analog-to-digital converter.
*/
typedef enum
{
NRF_SAADC_REFERENCE_INTERNAL = SAADC_CH_CONFIG_REFSEL_Internal, ///< Internal reference (0.6 V).
NRF_SAADC_REFERENCE_VDD4 = SAADC_CH_CONFIG_REFSEL_VDD1_4 ///< VDD/4 as reference.
} nrf_saadc_reference_t;
/**
* @brief Analog-to-digital converter acquisition time.
*/
typedef enum
{
NRF_SAADC_ACQTIME_3US = SAADC_CH_CONFIG_TACQ_3us, ///< 3 us.
NRF_SAADC_ACQTIME_5US = SAADC_CH_CONFIG_TACQ_5us, ///< 5 us.
NRF_SAADC_ACQTIME_10US = SAADC_CH_CONFIG_TACQ_10us, ///< 10 us.
NRF_SAADC_ACQTIME_15US = SAADC_CH_CONFIG_TACQ_15us, ///< 15 us.
NRF_SAADC_ACQTIME_20US = SAADC_CH_CONFIG_TACQ_20us, ///< 20 us.
NRF_SAADC_ACQTIME_40US = SAADC_CH_CONFIG_TACQ_40us ///< 40 us.
} nrf_saadc_acqtime_t;
/**
* @brief Analog-to-digital converter channel mode.
*/
typedef enum
{
NRF_SAADC_MODE_SINGLE_ENDED = SAADC_CH_CONFIG_MODE_SE, ///< Single ended, PSELN will be ignored, negative input to ADC shorted to GND.
NRF_SAADC_MODE_DIFFERENTIAL = SAADC_CH_CONFIG_MODE_Diff ///< Differential mode.
} nrf_saadc_mode_t;
/**
* @brief Analog-to-digital converter tasks.
*/
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
{
NRF_SAADC_TASK_START = offsetof(NRF_SAADC_Type, TASKS_START), ///< Start the ADC and prepare the result buffer in RAM.
NRF_SAADC_TASK_SAMPLE = offsetof(NRF_SAADC_Type, TASKS_SAMPLE), ///< Take one ADC sample. If scan is enabled, all channels are sampled.
NRF_SAADC_TASK_STOP = offsetof(NRF_SAADC_Type, TASKS_STOP), ///< Stop the ADC and terminate any on-going conversion.
NRF_SAADC_TASK_CALIBRATEOFFSET = offsetof(NRF_SAADC_Type, TASKS_CALIBRATEOFFSET), ///< Starts offset auto-calibration.
} nrf_saadc_task_t;
/**
* @brief Analog-to-digital converter events.
*/
typedef enum /*lint -save -e30 -esym(628,__INTADDR__) */
{
NRF_SAADC_EVENT_STARTED = offsetof(NRF_SAADC_Type, EVENTS_STARTED), ///< The ADC has started.
NRF_SAADC_EVENT_END = offsetof(NRF_SAADC_Type, EVENTS_END), ///< The ADC has filled up the result buffer.
NRF_SAADC_EVENT_CALIBRATEDONE = offsetof(NRF_SAADC_Type, EVENTS_CALIBRATEDONE), ///< Calibration is complete.
NRF_SAADC_EVENT_STOPPED = offsetof(NRF_SAADC_Type, EVENTS_STOPPED), ///< The ADC has stopped.
NRF_SAADC_EVENT_CH0_LIMITH = offsetof(NRF_SAADC_Type, EVENTS_CH[0].LIMITH), ///< Last result is equal or above CH[0].LIMIT.HIGH.
NRF_SAADC_EVENT_CH0_LIMITL = offsetof(NRF_SAADC_Type, EVENTS_CH[0].LIMITL), ///< Last result is equal or below CH[0].LIMIT.LOW.
NRF_SAADC_EVENT_CH1_LIMITH = offsetof(NRF_SAADC_Type, EVENTS_CH[1].LIMITH), ///< Last result is equal or above CH[1].LIMIT.HIGH.
NRF_SAADC_EVENT_CH1_LIMITL = offsetof(NRF_SAADC_Type, EVENTS_CH[1].LIMITL), ///< Last result is equal or below CH[1].LIMIT.LOW.
NRF_SAADC_EVENT_CH2_LIMITH = offsetof(NRF_SAADC_Type, EVENTS_CH[2].LIMITH), ///< Last result is equal or above CH[2].LIMIT.HIGH.
NRF_SAADC_EVENT_CH2_LIMITL = offsetof(NRF_SAADC_Type, EVENTS_CH[2].LIMITL), ///< Last result is equal or below CH[2].LIMIT.LOW.
NRF_SAADC_EVENT_CH3_LIMITH = offsetof(NRF_SAADC_Type, EVENTS_CH[3].LIMITH), ///< Last result is equal or above CH[3].LIMIT.HIGH.
NRF_SAADC_EVENT_CH3_LIMITL = offsetof(NRF_SAADC_Type, EVENTS_CH[3].LIMITL), ///< Last result is equal or below CH[3].LIMIT.LOW.
NRF_SAADC_EVENT_CH4_LIMITH = offsetof(NRF_SAADC_Type, EVENTS_CH[4].LIMITH), ///< Last result is equal or above CH[4].LIMIT.HIGH.
NRF_SAADC_EVENT_CH4_LIMITL = offsetof(NRF_SAADC_Type, EVENTS_CH[4].LIMITL), ///< Last result is equal or below CH[4].LIMIT.LOW.
NRF_SAADC_EVENT_CH5_LIMITH = offsetof(NRF_SAADC_Type, EVENTS_CH[5].LIMITH), ///< Last result is equal or above CH[5].LIMIT.HIGH.
NRF_SAADC_EVENT_CH5_LIMITL = offsetof(NRF_SAADC_Type, EVENTS_CH[5].LIMITL), ///< Last result is equal or below CH[5].LIMIT.LOW.
NRF_SAADC_EVENT_CH6_LIMITH = offsetof(NRF_SAADC_Type, EVENTS_CH[6].LIMITH), ///< Last result is equal or above CH[6].LIMIT.HIGH.
NRF_SAADC_EVENT_CH6_LIMITL = offsetof(NRF_SAADC_Type, EVENTS_CH[6].LIMITL), ///< Last result is equal or below CH[6].LIMIT.LOW.
NRF_SAADC_EVENT_CH7_LIMITH = offsetof(NRF_SAADC_Type, EVENTS_CH[7].LIMITH), ///< Last result is equal or above CH[7].LIMIT.HIGH.
NRF_SAADC_EVENT_CH7_LIMITL = offsetof(NRF_SAADC_Type, EVENTS_CH[7].LIMITL) ///< Last result is equal or below CH[7].LIMIT.LOW.
} nrf_saadc_event_t;
/**
* @brief Analog-to-digital converter interrupt masks.
*/
typedef enum
{
NRF_SAADC_INT_STARTED = SAADC_INTENSET_STARTED_Msk, ///< Interrupt on EVENTS_STARTED event.
NRF_SAADC_INT_END = SAADC_INTENSET_END_Msk, ///< Interrupt on EVENTS_END event.
NRF_SAADC_INT_STOPPED = SAADC_INTENSET_STOPPED_Msk, ///< Interrupt on EVENTS_STOPPED event.
NRF_SAADC_INT_CH0LIMITH = SAADC_INTENSET_CH0LIMITH_Msk, ///< Interrupt on EVENTS_CH[0].LIMITH event.
NRF_SAADC_INT_CH0LIMITL = SAADC_INTENSET_CH0LIMITL_Msk, ///< Interrupt on EVENTS_CH[0].LIMITL event.
NRF_SAADC_INT_CH1LIMITH = SAADC_INTENSET_CH1LIMITH_Msk, ///< Interrupt on EVENTS_CH[1].LIMITH event.
NRF_SAADC_INT_CH1LIMITL = SAADC_INTENSET_CH1LIMITL_Msk, ///< Interrupt on EVENTS_CH[1].LIMITL event.
NRF_SAADC_INT_CH2LIMITH = SAADC_INTENSET_CH2LIMITH_Msk, ///< Interrupt on EVENTS_CH[2].LIMITH event.
NRF_SAADC_INT_CH2LIMITL = SAADC_INTENSET_CH2LIMITL_Msk, ///< Interrupt on EVENTS_CH[2].LIMITL event.
NRF_SAADC_INT_CH3LIMITH = SAADC_INTENSET_CH3LIMITH_Msk, ///< Interrupt on EVENTS_CH[3].LIMITH event.
NRF_SAADC_INT_CH3LIMITL = SAADC_INTENSET_CH3LIMITL_Msk, ///< Interrupt on EVENTS_CH[3].LIMITL event.
NRF_SAADC_INT_CH4LIMITH = SAADC_INTENSET_CH4LIMITH_Msk, ///< Interrupt on EVENTS_CH[4].LIMITH event.
NRF_SAADC_INT_CH4LIMITL = SAADC_INTENSET_CH4LIMITL_Msk, ///< Interrupt on EVENTS_CH[4].LIMITL event.
NRF_SAADC_INT_CH5LIMITH = SAADC_INTENSET_CH5LIMITH_Msk, ///< Interrupt on EVENTS_CH[5].LIMITH event.
NRF_SAADC_INT_CH5LIMITL = SAADC_INTENSET_CH5LIMITL_Msk, ///< Interrupt on EVENTS_CH[5].LIMITL event.
NRF_SAADC_INT_CH6LIMITH = SAADC_INTENSET_CH6LIMITH_Msk, ///< Interrupt on EVENTS_CH[6].LIMITH event.
NRF_SAADC_INT_CH6LIMITL = SAADC_INTENSET_CH6LIMITL_Msk, ///< Interrupt on EVENTS_CH[6].LIMITL event.
NRF_SAADC_INT_CH7LIMITH = SAADC_INTENSET_CH7LIMITH_Msk, ///< Interrupt on EVENTS_CH[7].LIMITH event.
NRF_SAADC_INT_CH7LIMITL = SAADC_INTENSET_CH7LIMITL_Msk, ///< Interrupt on EVENTS_CH[7].LIMITL event.
NRF_SAADC_INT_ALL = 0x7FFFFFFFUL ///< Mask of all interrupts.
} nrf_saadc_int_mask_t;
/**
* @brief Analog-to-digital converter value limit type.
*/
typedef enum
{
NRF_SAADC_LIMIT_LOW = 0,
NRF_SAADC_LIMIT_HIGH = 1
} nrf_saadc_limit_t;
typedef int16_t nrf_saadc_value_t; ///< Type of a single ADC conversion result.
/**
* @brief Analog-to-digital converter configuration structure.
*/
typedef struct
{
nrf_saadc_resolution_t resolution;
nrf_saadc_oversample_t oversample;
nrf_saadc_value_t * buffer;
uint32_t buffer_size;
} nrf_saadc_config_t;
/**
* @brief Analog-to-digital converter channel configuration structure.
*/
typedef struct
{
nrf_saadc_resistor_t resistor_p;
nrf_saadc_resistor_t resistor_n;
nrf_saadc_gain_t gain;
nrf_saadc_reference_t reference;
nrf_saadc_acqtime_t acq_time;
nrf_saadc_mode_t mode;
nrf_saadc_input_t pin_p;
nrf_saadc_input_t pin_n;
} nrf_saadc_channel_config_t;
/**
* @brief Function for triggering a specific SAADC task.
*
* @param[in] saadc_task SAADC task.
*/
__STATIC_INLINE void nrf_saadc_task_trigger(nrf_saadc_task_t saadc_task)
{
*((volatile uint32_t *)((uint8_t *)NRF_SAADC + (uint32_t)saadc_task)) = 0x1UL;
}
/**
* @brief Function for getting the address of a specific SAADC task register.
*
* @param[in] saadc_task SAADC task.
*
* @return Address of the specified SAADC task.
*/
__STATIC_INLINE uint32_t nrf_saadc_task_address_get(nrf_saadc_task_t saadc_task)
{
return (uint32_t)((uint8_t *)NRF_SAADC + (uint32_t)saadc_task);
}
/**
* @brief Function for getting the state of a specific SAADC event.
*
* @param[in] saadc_event SAADC event.
*
* @return State of the specified SAADC event.
*/
__STATIC_INLINE bool nrf_saadc_event_check(nrf_saadc_event_t saadc_event)
{
return (bool)*(volatile uint32_t *)((uint8_t *)NRF_SAADC + (uint32_t)saadc_event);
}
/**
* @brief Function for clearing the specific SAADC event.
*
* @param[in] saadc_event SAADC event.
*/
__STATIC_INLINE void nrf_saadc_event_clear(nrf_saadc_event_t saadc_event)
{
*((volatile uint32_t *)((uint8_t *)NRF_SAADC + (uint32_t)saadc_event)) = 0x0UL;
}
/**
* @brief Function for getting the address of a specific SAADC event register.
*
* @param[in] saadc_event SAADC event.
*
* @return Address of the specified SAADC event.
*/
__STATIC_INLINE volatile uint32_t * nrf_saadc_event_address_get(nrf_saadc_event_t saadc_event)
{
return (volatile uint32_t *)((uint8_t *)NRF_SAADC + (uint32_t)saadc_event);
}
/**
* @brief Function for getting the address of a specific SAADC limit event register.
*
* @param[in] channel Channel number.
* @param[in] limit_type Low limit or high limit.
*
* @return Address of the specified SAADC limit event.
*/
__STATIC_INLINE volatile uint32_t * nrf_saadc_event_limit_address_get(uint8_t channel, nrf_saadc_limit_t limit_type)
{
ASSERT(channel < NRF_SAADC_CHANNEL_COUNT);
if (limit_type == NRF_SAADC_LIMIT_HIGH)
{
return &NRF_SAADC->EVENTS_CH[channel].LIMITH;
}
else
{
return &NRF_SAADC->EVENTS_CH[channel].LIMITL;
}
}
/**
* @brief Function for getting the SAADC channel monitoring limit events.
*
* @param[in] channel Channel number.
* @param[in] limit_type Low limit or high limit.
*/
__STATIC_INLINE nrf_saadc_event_t nrf_saadc_event_limit_get(uint8_t channel, nrf_saadc_limit_t limit_type)
{
if (limit_type == NRF_SAADC_LIMIT_HIGH)
{
return (nrf_saadc_event_t)( (uint32_t) NRF_SAADC_EVENT_CH0_LIMITH +
(uint32_t) (NRF_SAADC_EVENT_CH1_LIMITH - NRF_SAADC_EVENT_CH0_LIMITH)
* (uint32_t) channel );
}
else
{
return (nrf_saadc_event_t)( (uint32_t) NRF_SAADC_EVENT_CH0_LIMITL +
(uint32_t) (NRF_SAADC_EVENT_CH1_LIMITL - NRF_SAADC_EVENT_CH0_LIMITL)
* (uint32_t) channel );
}
}
/**
* @brief Function for configuring the input pins for a specific SAADC channel.
*
* @param[in] channel Channel number.
* @param[in] pselp Positive input.
* @param[in] pseln Negative input. Set to NRF_SAADC_INPUT_DISABLED in single ended mode.
*/
__STATIC_INLINE void nrf_saadc_channel_input_set(uint8_t channel,
nrf_saadc_input_t pselp,
nrf_saadc_input_t pseln)
{
NRF_SAADC->CH[channel].PSELN = pseln;
NRF_SAADC->CH[channel].PSELP = pselp;
}
/**
* @brief Function for setting the SAADC channel monitoring limits.
*
* @param[in] channel Channel number.
* @param[in] low Low limit.
* @param[in] high High limit.
*/
__STATIC_INLINE void nrf_saadc_channel_limits_set(uint8_t channel, int16_t low, int16_t high)
{
NRF_SAADC->CH[channel].LIMIT = (
(((uint32_t) low << SAADC_CH_LIMIT_LOW_Pos) & SAADC_CH_LIMIT_LOW_Msk)
| (((uint32_t) high << SAADC_CH_LIMIT_HIGH_Pos) & SAADC_CH_LIMIT_HIGH_Msk));
}
/**
* @brief Function for enabling specified SAADC interrupts.
*
* @param[in] saadc_int_mask Interrupt(s) to enable.
*/
__STATIC_INLINE void nrf_saadc_int_enable(uint32_t saadc_int_mask)
{
NRF_SAADC->INTENSET = saadc_int_mask;
}
/**
* @brief Function for retrieving the state of specified SAADC interrupts.
*
* @param[in] saadc_int_mask Interrupt(s) to check.
*
* @retval true If all specified interrupts are enabled.
* @retval false If at least one of the given interrupts is not enabled.
*/
__STATIC_INLINE bool nrf_saadc_int_enable_check(uint32_t saadc_int_mask)
{
return (bool)(NRF_SAADC->INTENSET & saadc_int_mask);
}
/**
* @brief Function for disabling specified interrupts.
*
* @param saadc_int_mask Interrupt(s) to disable.
*/
__STATIC_INLINE void nrf_saadc_int_disable(uint32_t saadc_int_mask)
{
NRF_SAADC->INTENCLR = saadc_int_mask;
}
/**
* @brief Function for generating masks for SAADC channel limit interrupts.
*
* @param[in] channel SAADC channel number.
* @param[in] limit_type Limit type.
*
* @returns Interrupt mask.
*/
__STATIC_INLINE uint32_t nrf_saadc_limit_int_get(uint8_t channel, nrf_saadc_limit_t limit_type)
{
ASSERT(channel < NRF_SAADC_CHANNEL_COUNT);
uint32_t mask = (limit_type == NRF_SAADC_LIMIT_LOW) ? NRF_SAADC_INT_CH0LIMITL : NRF_SAADC_INT_CH0LIMITH;
return mask << (channel * 2);
}
/**
* @brief Function for checking whether the SAADC is busy.
*
* This function checks whether the analog-to-digital converter is busy with a conversion.
*
* @retval true If the SAADC is busy.
* @retval false If the SAADC is not busy.
*/
__STATIC_INLINE bool nrf_saadc_busy_check(void)
{
//return ((NRF_SAADC->STATUS & SAADC_STATUS_STATUS_Msk) == SAADC_STATUS_STATUS_Msk);
//simplified for performance
return NRF_SAADC->STATUS;
}
/**
* @brief Function for enabling the SAADC.
*
* The analog-to-digital converter must be enabled before use.
*/
__STATIC_INLINE void nrf_saadc_enable(void)
{
NRF_SAADC->ENABLE = (SAADC_ENABLE_ENABLE_Enabled << SAADC_ENABLE_ENABLE_Pos);
}
/**
* @brief Function for disabling the SAADC.
*/
__STATIC_INLINE void nrf_saadc_disable(void)
{
NRF_SAADC->ENABLE = (SAADC_ENABLE_ENABLE_Disabled << SAADC_ENABLE_ENABLE_Pos);
}
/**
* @brief Function for checking if the SAADC is enabled.
*
* @retval true If the SAADC is enabled.
* @retval false If the SAADC is not enabled.
*/
__STATIC_INLINE bool nrf_saadc_enable_check(void)
{
//simplified for performance
return NRF_SAADC->ENABLE;
}
/**
* @brief Function for initializing the SAADC result buffer.
*
* @param[in] buffer Pointer to the result buffer.
* @param[in] num Size of buffer in words.
*/
__STATIC_INLINE void nrf_saadc_buffer_init(nrf_saadc_value_t * buffer, uint32_t num)
{
NRF_SAADC->RESULT.PTR = (uint32_t)buffer;
NRF_SAADC->RESULT.MAXCNT = num;
}
/**
* @brief Function for getting the number of buffer words transferred since last START operation.
*
* @returns Number of words transferred.
*/
__STATIC_INLINE uint16_t nrf_saadc_amount_get(void)
{
return NRF_SAADC->RESULT.AMOUNT;
}
/**
* @brief Function for setting the SAADC sample resolution.
*
* @param[in] resolution Bit resolution.
*/
__STATIC_INLINE void nrf_saadc_resolution_set(nrf_saadc_resolution_t resolution)
{
NRF_SAADC->RESOLUTION = resolution;
}
/**
* @brief Function for configuring the oversampling feature.
*
* @param[in] oversample Oversampling mode.
*/
__STATIC_INLINE void nrf_saadc_oversample_set(nrf_saadc_oversample_t oversample)
{
NRF_SAADC->OVERSAMPLE = oversample;
}
/**
* @brief Function for getting the oversampling feature configuration.
*
* @return Oversampling configuration.
*/
__STATIC_INLINE nrf_saadc_oversample_t nrf_saadc_oversample_get(void)
{
return (nrf_saadc_oversample_t)NRF_SAADC->OVERSAMPLE;
}
/**
* @brief Function for initializing the SAADC channel.
*
* @param[in] channel Channel number.
* @param[in] config Pointer to the channel configuration structure.
*/
void nrf_saadc_channel_init(uint8_t channel, nrf_saadc_channel_config_t const * const config);
/**
*@}
**/
#endif // NRF52
#endif /* NRF_SAADC_H_ */

View File

@ -1,361 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_spi_hal SPI HAL
* @{
* @ingroup nrf_spi_master
*
* @brief Hardware access layer for accessing the SPI peripheral.
*/
#ifndef NRF_SPI_H__
#define NRF_SPI_H__
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "nrf.h"
/**
* @brief This value can be used as a parameter for the @ref nrf_spi_pins_set
* function to specify that a given SPI signal (SCK, MOSI, or MISO)
* shall not be connected to a physical pin.
*/
#define NRF_SPI_PIN_NOT_CONNECTED 0xFFFFFFFF
/**
* @brief SPI events.
*/
typedef enum
{
/*lint -save -e30*/
NRF_SPI_EVENT_READY = offsetof(NRF_SPI_Type, EVENTS_READY) ///< TXD byte sent and RXD byte received.
/*lint -restore*/
} nrf_spi_event_t;
/**
* @brief SPI interrupts.
*/
typedef enum
{
NRF_SPI_INT_READY_MASK = SPI_INTENSET_READY_Msk ///< Interrupt on READY event.
} nrf_spi_int_mask_t;
/**
* @brief SPI data rates.
*/
typedef enum
{
NRF_SPI_FREQ_125K = SPI_FREQUENCY_FREQUENCY_K125, ///< 125 kbps.
NRF_SPI_FREQ_250K = SPI_FREQUENCY_FREQUENCY_K250, ///< 250 kbps.
NRF_SPI_FREQ_500K = SPI_FREQUENCY_FREQUENCY_K500, ///< 500 kbps.
NRF_SPI_FREQ_1M = SPI_FREQUENCY_FREQUENCY_M1, ///< 1 Mbps.
NRF_SPI_FREQ_2M = SPI_FREQUENCY_FREQUENCY_M2, ///< 2 Mbps.
NRF_SPI_FREQ_4M = SPI_FREQUENCY_FREQUENCY_M4, ///< 4 Mbps.
// [conversion to 'int' needed to prevent compilers from complaining
// that the provided value (0x80000000UL) is out of range of "int"]
NRF_SPI_FREQ_8M = (int)SPI_FREQUENCY_FREQUENCY_M8 ///< 8 Mbps.
} nrf_spi_frequency_t;
/**
* @brief SPI modes.
*/
typedef enum
{
NRF_SPI_MODE_0, ///< SCK active high, sample on leading edge of clock.
NRF_SPI_MODE_1, ///< SCK active high, sample on trailing edge of clock.
NRF_SPI_MODE_2, ///< SCK active low, sample on leading edge of clock.
NRF_SPI_MODE_3 ///< SCK active low, sample on trailing edge of clock.
} nrf_spi_mode_t;
/**
* @brief SPI bit orders.
*/
typedef enum
{
NRF_SPI_BIT_ORDER_MSB_FIRST = SPI_CONFIG_ORDER_MsbFirst, ///< Most significant bit shifted out first.
NRF_SPI_BIT_ORDER_LSB_FIRST = SPI_CONFIG_ORDER_LsbFirst ///< Least significant bit shifted out first.
} nrf_spi_bit_order_t;
/**
* @brief Function for clearing a specific SPI event.
*
* @param[in] p_spi SPI instance.
* @param[in] spi_event Event to clear.
*/
__STATIC_INLINE void nrf_spi_event_clear(NRF_SPI_Type * p_spi,
nrf_spi_event_t spi_event);
/**
* @brief Function for checking the state of a specific SPI event.
*
* @param[in] p_spi SPI instance.
* @param[in] spi_event Event to check.
*
* @retval true If the event is set.
* @retval false If the event is not set.
*/
__STATIC_INLINE bool nrf_spi_event_check(NRF_SPI_Type * p_spi,
nrf_spi_event_t spi_event);
/**
* @brief Function for getting the address of a specific SPI event register.
*
* @param[in] p_spi SPI instance.
* @param[in] spi_event Requested event.
*
* @return Address of the specified event register.
*/
__STATIC_INLINE uint32_t * nrf_spi_event_address_get(NRF_SPI_Type * p_spi,
nrf_spi_event_t spi_event);
/**
* @brief Function for enabling specified interrupts.
*
* @param[in] p_spi SPI instance.
* @param[in] spi_int_mask Interrupts to enable.
*/
__STATIC_INLINE void nrf_spi_int_enable(NRF_SPI_Type * p_spi,
uint32_t spi_int_mask);
/**
* @brief Function for disabling specified interrupts.
*
* @param[in] p_spi SPI instance.
* @param[in] spi_int_mask Interrupts to disable.
*/
__STATIC_INLINE void nrf_spi_int_disable(NRF_SPI_Type * p_spi,
uint32_t spi_int_mask);
/**
* @brief Function for retrieving the state of a given interrupt.
*
* @param[in] p_spi SPI instance.
* @param[in] spi_int Interrupt to check.
*
* @retval true If the interrupt is enabled.
* @retval false If the interrupt is not enabled.
*/
__STATIC_INLINE bool nrf_spi_int_enable_check(NRF_SPI_Type * p_spi,
nrf_spi_int_mask_t spi_int);
/**
* @brief Function for enabling the SPI peripheral.
*
* @param[in] p_spi SPI instance.
*/
__STATIC_INLINE void nrf_spi_enable(NRF_SPI_Type * p_spi);
/**
* @brief Function for disabling the SPI peripheral.
*
* @param[in] p_spi SPI instance.
*/
__STATIC_INLINE void nrf_spi_disable(NRF_SPI_Type * p_spi);
/**
* @brief Function for configuring SPI pins.
*
* If a given signal is not needed, pass the @ref NRF_SPI_PIN_NOT_CONNECTED
* value instead of its pin number.
*
* @param[in] p_spi SPI instance.
* @param[in] sck_pin SCK pin number.
* @param[in] mosi_pin MOSI pin number.
* @param[in] miso_pin MISO pin number.
*/
__STATIC_INLINE void nrf_spi_pins_set(NRF_SPI_Type * p_spi,
uint32_t sck_pin,
uint32_t mosi_pin,
uint32_t miso_pin);
/**
* @brief Function for writing data to the SPI transmitter register.
*
* @param[in] p_spi SPI instance.
* @param[in] data TX data to send.
*/
__STATIC_INLINE void nrf_spi_txd_set(NRF_SPI_Type * p_spi, uint8_t data);
/**
* @brief Function for reading data from the SPI receiver register.
*
* @param[in] p_spi SPI instance.
*
* @return RX data received.
*/
__STATIC_INLINE uint8_t nrf_spi_rxd_get(NRF_SPI_Type * p_spi);
/**
* @brief Function for setting the SPI master data rate.
*
* @param[in] p_spi SPI instance.
* @param[in] frequency SPI frequency.
*/
__STATIC_INLINE void nrf_spi_frequency_set(NRF_SPI_Type * p_spi,
nrf_spi_frequency_t frequency);
/**
* @brief Function for setting the SPI configuration.
*
* @param[in] p_spi SPI instance.
* @param[in] spi_mode SPI mode.
* @param[in] spi_bit_order SPI bit order.
*/
__STATIC_INLINE void nrf_spi_configure(NRF_SPI_Type * p_spi,
nrf_spi_mode_t spi_mode,
nrf_spi_bit_order_t spi_bit_order);
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE void nrf_spi_event_clear(NRF_SPI_Type * p_spi,
nrf_spi_event_t spi_event)
{
*((volatile uint32_t *)((uint8_t *)p_spi + (uint32_t)spi_event)) = 0x0UL;
}
__STATIC_INLINE bool nrf_spi_event_check(NRF_SPI_Type * p_spi,
nrf_spi_event_t spi_event)
{
return (bool)*(volatile uint32_t *)((uint8_t *)p_spi + (uint32_t)spi_event);
}
__STATIC_INLINE uint32_t * nrf_spi_event_address_get(NRF_SPI_Type * p_spi,
nrf_spi_event_t spi_event)
{
return (uint32_t *)((uint8_t *)p_spi + (uint32_t)spi_event);
}
__STATIC_INLINE void nrf_spi_int_enable(NRF_SPI_Type * p_spi,
uint32_t spi_int_mask)
{
p_spi->INTENSET = spi_int_mask;
}
__STATIC_INLINE void nrf_spi_int_disable(NRF_SPI_Type * p_spi,
uint32_t spi_int_mask)
{
p_spi->INTENCLR = spi_int_mask;
}
__STATIC_INLINE bool nrf_spi_int_enable_check(NRF_SPI_Type * p_spi,
nrf_spi_int_mask_t spi_int)
{
return (bool)(p_spi->INTENSET & spi_int);
}
__STATIC_INLINE void nrf_spi_enable(NRF_SPI_Type * p_spi)
{
p_spi->ENABLE = (SPI_ENABLE_ENABLE_Enabled << SPI_ENABLE_ENABLE_Pos);
}
__STATIC_INLINE void nrf_spi_disable(NRF_SPI_Type * p_spi)
{
p_spi->ENABLE = (SPI_ENABLE_ENABLE_Disabled << SPI_ENABLE_ENABLE_Pos);
}
__STATIC_INLINE void nrf_spi_pins_set(NRF_SPI_Type * p_spi,
uint32_t sck_pin,
uint32_t mosi_pin,
uint32_t miso_pin)
{
p_spi->PSELSCK = sck_pin;
p_spi->PSELMOSI = mosi_pin;
p_spi->PSELMISO = miso_pin;
}
__STATIC_INLINE void nrf_spi_txd_set(NRF_SPI_Type * p_spi, uint8_t data)
{
p_spi->TXD = data;
}
__STATIC_INLINE uint8_t nrf_spi_rxd_get(NRF_SPI_Type * p_spi)
{
return p_spi->RXD;
}
__STATIC_INLINE void nrf_spi_frequency_set(NRF_SPI_Type * p_spi,
nrf_spi_frequency_t frequency)
{
p_spi->FREQUENCY = frequency;
}
__STATIC_INLINE void nrf_spi_configure(NRF_SPI_Type * p_spi,
nrf_spi_mode_t spi_mode,
nrf_spi_bit_order_t spi_bit_order)
{
uint32_t config = (spi_bit_order == NRF_SPI_BIT_ORDER_MSB_FIRST ?
SPI_CONFIG_ORDER_MsbFirst : SPI_CONFIG_ORDER_LsbFirst);
switch (spi_mode)
{
default:
case NRF_SPI_MODE_0:
config |= (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos) |
(SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos);
break;
case NRF_SPI_MODE_1:
config |= (SPI_CONFIG_CPOL_ActiveHigh << SPI_CONFIG_CPOL_Pos) |
(SPI_CONFIG_CPHA_Trailing << SPI_CONFIG_CPHA_Pos);
break;
case NRF_SPI_MODE_2:
config |= (SPI_CONFIG_CPOL_ActiveLow << SPI_CONFIG_CPOL_Pos) |
(SPI_CONFIG_CPHA_Leading << SPI_CONFIG_CPHA_Pos);
break;
case NRF_SPI_MODE_3:
config |= (SPI_CONFIG_CPOL_ActiveLow << SPI_CONFIG_CPOL_Pos) |
(SPI_CONFIG_CPHA_Trailing << SPI_CONFIG_CPHA_Pos);
break;
}
p_spi->CONFIG = config;
}
#endif // SUPPRESS_INLINE_IMPLEMENTATION
#endif // NRF_SPI_H__
/** @} */

View File

@ -1,547 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_spim_hal SPIM HAL
* @{
* @ingroup nrf_spi_master
*
* @brief Hardware access layer for accessing the SPIM peripheral.
*/
#ifndef NRF_SPIM_H__
#define NRF_SPIM_H__
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "nrf.h"
/**
* @brief This value can be used as a parameter for the @ref nrf_spim_pins_set
* function to specify that a given SPI signal (SCK, MOSI, or MISO)
* shall not be connected to a physical pin.
*/
#define NRF_SPIM_PIN_NOT_CONNECTED 0xFFFFFFFF
/**
* @brief SPIM tasks.
*/
typedef enum
{
/*lint -save -e30*/
NRF_SPIM_TASK_START = offsetof(NRF_SPIM_Type, TASKS_START), ///< Start SPI transaction.
NRF_SPIM_TASK_STOP = offsetof(NRF_SPIM_Type, TASKS_STOP), ///< Stop SPI transaction.
NRF_SPIM_TASK_SUSPEND = offsetof(NRF_SPIM_Type, TASKS_SUSPEND), ///< Suspend SPI transaction.
NRF_SPIM_TASK_RESUME = offsetof(NRF_SPIM_Type, TASKS_RESUME) ///< Resume SPI transaction.
/*lint -restore*/
} nrf_spim_task_t;
/**
* @brief SPIM events.
*/
typedef enum
{
/*lint -save -e30*/
NRF_SPIM_EVENT_STOPPED = offsetof(NRF_SPIM_Type, EVENTS_STOPPED), ///< SPI transaction has stopped.
NRF_SPIM_EVENT_ENDRX = offsetof(NRF_SPIM_Type, EVENTS_ENDRX), ///< End of RXD buffer reached.
#ifdef NRF52
NRF_SPIM_EVENT_END = offsetof(NRF_SPIM_Type, EVENTS_END), ///< End of RXD buffer and TXD buffer reached.
#endif
NRF_SPIM_EVENT_ENDTX = offsetof(NRF_SPIM_Type, EVENTS_ENDTX), ///< End of TXD buffer reached.
NRF_SPIM_EVENT_STARTED = offsetof(NRF_SPIM_Type, EVENTS_STARTED) ///< Transaction started.
/*lint -restore*/
} nrf_spim_event_t;
#ifdef NRF52
/**
* @brief SPIM shortcuts.
*/
typedef enum
{
NRF_SPIM_SHORT_END_START_MASK = SPIM_SHORTS_END_START_Msk ///< Shortcut between END event and START task.
} nrf_spim_short_mask_t;
#endif
/**
* @brief SPIM interrupts.
*/
typedef enum
{
NRF_SPIM_INT_STOPPED_MASK = SPIM_INTENSET_STOPPED_Msk, ///< Interrupt on STOPPED event.
NRF_SPIM_INT_ENDRX_MASK = SPIM_INTENSET_ENDRX_Msk, ///< Interrupt on ENDRX event.
#ifdef NRF52
NRF_SPIM_INT_END_MASK = SPIM_INTENSET_END_Msk, ///< Interrupt on END event.
#endif
NRF_SPIM_INT_ENDTX_MASK = SPIM_INTENSET_ENDTX_Msk, ///< Interrupt on ENDTX event.
NRF_SPIM_INT_STARTED_MASK = SPIM_INTENSET_STARTED_Msk ///< Interrupt on STARTED event.
} nrf_spim_int_mask_t;
/**
* @brief SPI master data rates.
*/
typedef enum
{
NRF_SPIM_FREQ_125K = SPIM_FREQUENCY_FREQUENCY_K125, ///< 125 kbps.
NRF_SPIM_FREQ_250K = SPIM_FREQUENCY_FREQUENCY_K250, ///< 250 kbps.
NRF_SPIM_FREQ_500K = SPIM_FREQUENCY_FREQUENCY_K500, ///< 500 kbps.
NRF_SPIM_FREQ_1M = SPIM_FREQUENCY_FREQUENCY_M1, ///< 1 Mbps.
NRF_SPIM_FREQ_2M = SPIM_FREQUENCY_FREQUENCY_M2, ///< 2 Mbps.
NRF_SPIM_FREQ_4M = SPIM_FREQUENCY_FREQUENCY_M4, ///< 4 Mbps.
// [conversion to 'int' needed to prevent compilers from complaining
// that the provided value (0x80000000UL) is out of range of "int"]
NRF_SPIM_FREQ_8M = (int)SPIM_FREQUENCY_FREQUENCY_M8 ///< 8 Mbps.
} nrf_spim_frequency_t;
/**
* @brief SPI modes.
*/
typedef enum
{
NRF_SPIM_MODE_0, ///< SCK active high, sample on leading edge of clock.
NRF_SPIM_MODE_1, ///< SCK active high, sample on trailing edge of clock.
NRF_SPIM_MODE_2, ///< SCK active low, sample on leading edge of clock.
NRF_SPIM_MODE_3 ///< SCK active low, sample on trailing edge of clock.
} nrf_spim_mode_t;
/**
* @brief SPI bit orders.
*/
typedef enum
{
NRF_SPIM_BIT_ORDER_MSB_FIRST = SPIM_CONFIG_ORDER_MsbFirst, ///< Most significant bit shifted out first.
NRF_SPIM_BIT_ORDER_LSB_FIRST = SPIM_CONFIG_ORDER_LsbFirst ///< Least significant bit shifted out first.
} nrf_spim_bit_order_t;
/**
* @brief Function for activating a specific SPIM task.
*
* @param[in] p_spim SPIM instance.
* @param[in] spim_task Task to activate.
*/
__STATIC_INLINE void nrf_spim_task_trigger(NRF_SPIM_Type * p_spim,
nrf_spim_task_t spim_task);
/**
* @brief Function for getting the address of a specific SPIM task register.
*
* @param[in] p_spim SPIM instance.
* @param[in] spim_task Requested task.
*
* @return Address of the specified task register.
*/
__STATIC_INLINE uint32_t nrf_spim_task_address_get(NRF_SPIM_Type * p_spim,
nrf_spim_task_t spim_task);
/**
* @brief Function for clearing a specific SPIM event.
*
* @param[in] p_spim SPIM instance.
* @param[in] spim_event Event to clear.
*/
__STATIC_INLINE void nrf_spim_event_clear(NRF_SPIM_Type * p_spim,
nrf_spim_event_t spim_event);
/**
* @brief Function for checking the state of a specific SPIM event.
*
* @param[in] p_spim SPIM instance.
* @param[in] spim_event Event to check.
*
* @retval true If the event is set.
* @retval false If the event is not set.
*/
__STATIC_INLINE bool nrf_spim_event_check(NRF_SPIM_Type * p_spim,
nrf_spim_event_t spim_event);
/**
* @brief Function for getting the address of a specific SPIM event register.
*
* @param[in] p_spim SPIM instance.
* @param[in] spim_event Requested event.
*
* @return Address of the specified event register.
*/
__STATIC_INLINE uint32_t nrf_spim_event_address_get(NRF_SPIM_Type * p_spim,
nrf_spim_event_t spim_event);
#ifdef NRF52
/**
* @brief Function for enabling specified shortcuts.
*
* @param[in] p_spim SPIM instance.
* @param[in] spim_shorts_mask Shortcuts to enable.
*/
__STATIC_INLINE void nrf_spim_shorts_enable(NRF_SPIM_Type * p_spim,
uint32_t spim_shorts_mask);
/**
* @brief Function for disabling specified shortcuts.
*
* @param[in] p_spim SPIM instance.
* @param[in] spim_shorts_mask Shortcuts to disable.
*/
__STATIC_INLINE void nrf_spim_shorts_disable(NRF_SPIM_Type * p_spim,
uint32_t spim_shorts_mask);
/**
* @brief Function for getting shorts setting.
*
* @param[in] p_spim SPIM instance.
*/
__STATIC_INLINE uint32_t nrf_spim_shorts_get(NRF_SPIM_Type * p_spim);
#endif
/**
* @brief Function for enabling specified interrupts.
*
* @param[in] p_spim SPIM instance.
* @param[in] spim_int_mask Interrupts to enable.
*/
__STATIC_INLINE void nrf_spim_int_enable(NRF_SPIM_Type * p_spim,
uint32_t spim_int_mask);
/**
* @brief Function for disabling specified interrupts.
*
* @param[in] p_spim SPIM instance.
* @param[in] spim_int_mask Interrupts to disable.
*/
__STATIC_INLINE void nrf_spim_int_disable(NRF_SPIM_Type * p_spim,
uint32_t spim_int_mask);
/**
* @brief Function for retrieving the state of a given interrupt.
*
* @param[in] p_spim SPIM instance.
* @param[in] spim_int Interrupt to check.
*
* @retval true If the interrupt is enabled.
* @retval false If the interrupt is not enabled.
*/
__STATIC_INLINE bool nrf_spim_int_enable_check(NRF_SPIM_Type * p_spim,
nrf_spim_int_mask_t spim_int);
/**
* @brief Function for enabling the SPIM peripheral.
*
* @param[in] p_spim SPIM instance.
*/
__STATIC_INLINE void nrf_spim_enable(NRF_SPIM_Type * p_spim);
/**
* @brief Function for disabling the SPIM peripheral.
*
* @param[in] p_spim SPIM instance.
*/
__STATIC_INLINE void nrf_spim_disable(NRF_SPIM_Type * p_spim);
/**
* @brief Function for configuring SPIM pins.
*
* If a given signal is not needed, pass the @ref NRF_SPIM_PIN_NOT_CONNECTED
* value instead of its pin number.
*
* @param[in] p_spim SPIM instance.
* @param[in] sck_pin SCK pin number.
* @param[in] mosi_pin MOSI pin number.
* @param[in] miso_pin MISO pin number.
*/
__STATIC_INLINE void nrf_spim_pins_set(NRF_SPIM_Type * p_spim,
uint32_t sck_pin,
uint32_t mosi_pin,
uint32_t miso_pin);
/**
* @brief Function for setting the SPI master data rate.
*
* @param[in] p_spim SPIM instance.
* @param[in] frequency SPI frequency.
*/
__STATIC_INLINE void nrf_spim_frequency_set(NRF_SPIM_Type * p_spim,
nrf_spim_frequency_t frequency);
/**
* @brief Function for setting the transmit buffer.
*
* @param[in] p_spim SPIM instance.
* @param[in] p_buffer Pointer to the buffer with data to send.
* @param[in] length Maximum number of data bytes to transmit.
*/
__STATIC_INLINE void nrf_spim_tx_buffer_set(NRF_SPIM_Type * p_spim,
uint8_t const * p_buffer,
uint8_t length);
/**
* @brief Function for setting the receive buffer.
*
* @param[in] p_spim SPIM instance.
* @param[in] p_buffer Pointer to the buffer for received data.
* @param[in] length Maximum number of data bytes to receive.
*/
__STATIC_INLINE void nrf_spim_rx_buffer_set(NRF_SPIM_Type * p_spim,
uint8_t * p_buffer,
uint8_t length);
/**
* @brief Function for setting the SPI configuration.
*
* @param[in] p_spim SPIM instance.
* @param[in] spi_mode SPI mode.
* @param[in] spi_bit_order SPI bit order.
*/
__STATIC_INLINE void nrf_spim_configure(NRF_SPIM_Type * p_spim,
nrf_spim_mode_t spi_mode,
nrf_spim_bit_order_t spi_bit_order);
/**
* @brief Function for setting the over-read character.
*
* @param[in] p_spim SPIM instance.
* @param[in] orc Over-read character that is clocked out in case of
* an over-read of the TXD buffer.
*/
__STATIC_INLINE void nrf_spim_orc_set(NRF_SPIM_Type * p_spim,
uint8_t orc);
#ifdef NRF52
/**
* @brief Function for enabling the TX list feature.
*
* @param[in] p_spim SPIM instance.
*/
__STATIC_INLINE void nrf_spim_tx_list_enable(NRF_SPIM_Type * p_spim);
/**
* @brief Function for disabling the TX list feature.
*
* @param[in] p_spim SPIM instance.
*/
__STATIC_INLINE void nrf_spim_tx_list_disable(NRF_SPIM_Type * p_spim);
/**
* @brief Function for enabling the RX list feature.
*
* @param[in] p_spim SPIM instance.
*/
__STATIC_INLINE void nrf_spim_rx_list_enable(NRF_SPIM_Type * p_spim);
/**
* @brief Function for disabling the RX list feature.
*
* @param[in] p_spim SPIM instance.
*/
__STATIC_INLINE void nrf_spim_rx_list_disable(NRF_SPIM_Type * p_spim);
#endif
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE void nrf_spim_task_trigger(NRF_SPIM_Type * p_spim,
nrf_spim_task_t spim_task)
{
*((volatile uint32_t *)((uint8_t *)p_spim + (uint32_t)spim_task)) = 0x1UL;
}
__STATIC_INLINE uint32_t nrf_spim_task_address_get(NRF_SPIM_Type * p_spim,
nrf_spim_task_t spim_task)
{
return (uint32_t)((uint8_t *)p_spim + (uint32_t)spim_task);
}
__STATIC_INLINE void nrf_spim_event_clear(NRF_SPIM_Type * p_spim,
nrf_spim_event_t spim_event)
{
*((volatile uint32_t *)((uint8_t *)p_spim + (uint32_t)spim_event)) = 0x0UL;
}
__STATIC_INLINE bool nrf_spim_event_check(NRF_SPIM_Type * p_spim,
nrf_spim_event_t spim_event)
{
return (bool)*(volatile uint32_t *)((uint8_t *)p_spim + (uint32_t)spim_event);
}
__STATIC_INLINE uint32_t nrf_spim_event_address_get(NRF_SPIM_Type * p_spim,
nrf_spim_event_t spim_event)
{
return (uint32_t)((uint8_t *)p_spim + (uint32_t)spim_event);
}
#ifdef NRF52
__STATIC_INLINE void nrf_spim_shorts_enable(NRF_SPIM_Type * p_spim,
uint32_t spim_shorts_mask)
{
p_spim->SHORTS |= spim_shorts_mask;
}
__STATIC_INLINE void nrf_spim_shorts_disable(NRF_SPIM_Type * p_spim,
uint32_t spim_shorts_mask)
{
p_spim->SHORTS &= ~(spim_shorts_mask);
}
__STATIC_INLINE uint32_t nrf_spim_shorts_get(NRF_SPIM_Type * p_spim)
{
return p_spim->SHORTS;
}
#endif
__STATIC_INLINE void nrf_spim_int_enable(NRF_SPIM_Type * p_spim,
uint32_t spim_int_mask)
{
p_spim->INTENSET = spim_int_mask;
}
__STATIC_INLINE void nrf_spim_int_disable(NRF_SPIM_Type * p_spim,
uint32_t spim_int_mask)
{
p_spim->INTENCLR = spim_int_mask;
}
__STATIC_INLINE bool nrf_spim_int_enable_check(NRF_SPIM_Type * p_spim,
nrf_spim_int_mask_t spim_int)
{
return (bool)(p_spim->INTENSET & spim_int);
}
__STATIC_INLINE void nrf_spim_enable(NRF_SPIM_Type * p_spim)
{
p_spim->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos);
}
__STATIC_INLINE void nrf_spim_disable(NRF_SPIM_Type * p_spim)
{
p_spim->ENABLE = (SPIM_ENABLE_ENABLE_Disabled << SPIM_ENABLE_ENABLE_Pos);
}
__STATIC_INLINE void nrf_spim_pins_set(NRF_SPIM_Type * p_spim,
uint32_t sck_pin,
uint32_t mosi_pin,
uint32_t miso_pin)
{
p_spim->PSEL.SCK = sck_pin;
p_spim->PSEL.MOSI = mosi_pin;
p_spim->PSEL.MISO = miso_pin;
}
__STATIC_INLINE void nrf_spim_frequency_set(NRF_SPIM_Type * p_spim,
nrf_spim_frequency_t frequency)
{
p_spim->FREQUENCY = frequency;
}
__STATIC_INLINE void nrf_spim_tx_buffer_set(NRF_SPIM_Type * p_spim,
uint8_t const * p_buffer,
uint8_t length)
{
p_spim->TXD.PTR = (uint32_t)p_buffer;
p_spim->TXD.MAXCNT = length;
}
__STATIC_INLINE void nrf_spim_rx_buffer_set(NRF_SPIM_Type * p_spim,
uint8_t * p_buffer,
uint8_t length)
{
p_spim->RXD.PTR = (uint32_t)p_buffer;
p_spim->RXD.MAXCNT = length;
}
__STATIC_INLINE void nrf_spim_configure(NRF_SPIM_Type * p_spim,
nrf_spim_mode_t spi_mode,
nrf_spim_bit_order_t spi_bit_order)
{
uint32_t config = (spi_bit_order == NRF_SPIM_BIT_ORDER_MSB_FIRST ?
SPIM_CONFIG_ORDER_MsbFirst : SPIM_CONFIG_ORDER_LsbFirst);
switch (spi_mode)
{
default:
case NRF_SPIM_MODE_0:
config |= (SPIM_CONFIG_CPOL_ActiveHigh << SPIM_CONFIG_CPOL_Pos) |
(SPIM_CONFIG_CPHA_Leading << SPIM_CONFIG_CPHA_Pos);
break;
case NRF_SPIM_MODE_1:
config |= (SPIM_CONFIG_CPOL_ActiveHigh << SPIM_CONFIG_CPOL_Pos) |
(SPIM_CONFIG_CPHA_Trailing << SPIM_CONFIG_CPHA_Pos);
break;
case NRF_SPIM_MODE_2:
config |= (SPIM_CONFIG_CPOL_ActiveLow << SPIM_CONFIG_CPOL_Pos) |
(SPIM_CONFIG_CPHA_Leading << SPIM_CONFIG_CPHA_Pos);
break;
case NRF_SPIM_MODE_3:
config |= (SPIM_CONFIG_CPOL_ActiveLow << SPIM_CONFIG_CPOL_Pos) |
(SPIM_CONFIG_CPHA_Trailing << SPIM_CONFIG_CPHA_Pos);
break;
}
p_spim->CONFIG = config;
}
__STATIC_INLINE void nrf_spim_orc_set(NRF_SPIM_Type * p_spim,
uint8_t orc)
{
p_spim->ORC = orc;
}
#ifdef NRF52
__STATIC_INLINE void nrf_spim_tx_list_enable(NRF_SPIM_Type * p_spim)
{
p_spim->TXD.LIST = 1;
}
__STATIC_INLINE void nrf_spim_tx_list_disable(NRF_SPIM_Type * p_spim)
{
p_spim->TXD.LIST = 0;
}
__STATIC_INLINE void nrf_spim_rx_list_enable(NRF_SPIM_Type * p_spim)
{
p_spim->RXD.LIST = 1;
}
__STATIC_INLINE void nrf_spim_rx_list_disable(NRF_SPIM_Type * p_spim)
{
p_spim->RXD.LIST = 0;
}
#endif
#endif // SUPPRESS_INLINE_IMPLEMENTATION
#endif // NRF_SPIM_H__
/** @} */

View File

@ -1,539 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_spis_hal SPIS HAL
* @{
* @ingroup nrf_spis
*
* @brief Hardware access layer for accessing the SPIS peripheral.
*/
#ifndef NRF_SPIS_H__
#define NRF_SPIS_H__
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "nrf.h"
/**
* @brief This value can be used as a parameter for the @ref nrf_spis_pins_set
* function to specify that a given SPI signal (SCK, MOSI, or MISO)
* shall not be connected to a physical pin.
*/
#define NRF_SPIS_PIN_NOT_CONNECTED 0xFFFFFFFF
/**
* @brief SPIS tasks.
*/
typedef enum
{
/*lint -save -e30*/
NRF_SPIS_TASK_ACQUIRE = offsetof(NRF_SPIS_Type, TASKS_ACQUIRE), ///< Acquire SPI semaphore.
NRF_SPIS_TASK_RELEASE = offsetof(NRF_SPIS_Type, TASKS_RELEASE), ///< Release SPI semaphore, enabling the SPI slave to acquire it.
/*lint -restore*/
} nrf_spis_task_t;
/**
* @brief SPIS events.
*/
typedef enum
{
/*lint -save -e30*/
NRF_SPIS_EVENT_END = offsetof(NRF_SPIS_Type, EVENTS_END), ///< Granted transaction completed.
NRF_SPIS_EVENT_ACQUIRED = offsetof(NRF_SPIS_Type, EVENTS_ACQUIRED) ///< Semaphore acquired.
/*lint -restore*/
} nrf_spis_event_t;
/**
* @brief SPIS shortcuts.
*/
typedef enum
{
NRF_SPIS_SHORT_END_ACQUIRE = SPIS_SHORTS_END_ACQUIRE_Msk ///< Shortcut between END event and ACQUIRE task.
} nrf_spis_short_mask_t;
/**
* @brief SPIS interrupts.
*/
typedef enum
{
NRF_SPIS_INT_END_MASK = SPIS_INTENSET_END_Msk, ///< Interrupt on END event.
NRF_SPIS_INT_ACQUIRED_MASK = SPIS_INTENSET_ACQUIRED_Msk ///< Interrupt on ACQUIRED event.
} nrf_spis_int_mask_t;
/**
* @brief SPI modes.
*/
typedef enum
{
NRF_SPIS_MODE_0, ///< SCK active high, sample on leading edge of clock.
NRF_SPIS_MODE_1, ///< SCK active high, sample on trailing edge of clock.
NRF_SPIS_MODE_2, ///< SCK active low, sample on leading edge of clock.
NRF_SPIS_MODE_3 ///< SCK active low, sample on trailing edge of clock.
} nrf_spis_mode_t;
/**
* @brief SPI bit orders.
*/
typedef enum
{
NRF_SPIS_BIT_ORDER_MSB_FIRST = SPIS_CONFIG_ORDER_MsbFirst, ///< Most significant bit shifted out first.
NRF_SPIS_BIT_ORDER_LSB_FIRST = SPIS_CONFIG_ORDER_LsbFirst ///< Least significant bit shifted out first.
} nrf_spis_bit_order_t;
/**
* @brief SPI semaphore status.
*/
typedef enum
{
NRF_SPIS_SEMSTAT_FREE = 0, ///< Semaphore is free.
NRF_SPIS_SEMSTAT_CPU = 1, ///< Semaphore is assigned to the CPU.
NRF_SPIS_SEMSTAT_SPIS = 2, ///< Semaphore is assigned to the SPI slave.
NRF_SPIS_SEMSTAT_CPUPENDING = 3 ///< Semaphore is assigned to the SPI, but a handover to the CPU is pending.
} nrf_spis_semstat_t;
/**
* @brief SPIS status.
*/
typedef enum
{
NRF_SPIS_STATUS_OVERREAD = SPIS_STATUS_OVERREAD_Msk, ///< TX buffer over-read detected and prevented.
NRF_SPIS_STATUS_OVERFLOW = SPIS_STATUS_OVERFLOW_Msk ///< RX buffer overflow detected and prevented.
} nrf_spis_status_mask_t;
/**
* @brief Function for activating a specific SPIS task.
*
* @param[in] p_spis SPIS instance.
* @param[in] spis_task Task to activate.
*/
__STATIC_INLINE void nrf_spis_task_trigger(NRF_SPIS_Type * p_spis,
nrf_spis_task_t spis_task);
/**
* @brief Function for getting the address of a specific SPIS task register.
*
* @param[in] p_spis SPIS instance.
* @param[in] spis_task Requested task.
*
* @return Address of the specified task register.
*/
__STATIC_INLINE uint32_t nrf_spis_task_address_get(NRF_SPIS_Type const * p_spis,
nrf_spis_task_t spis_task);
/**
* @brief Function for clearing a specific SPIS event.
*
* @param[in] p_spis SPIS instance.
* @param[in] spis_event Event to clear.
*/
__STATIC_INLINE void nrf_spis_event_clear(NRF_SPIS_Type * p_spis,
nrf_spis_event_t spis_event);
/**
* @brief Function for checking the state of a specific SPIS event.
*
* @param[in] p_spis SPIS instance.
* @param[in] spis_event Event to check.
*
* @retval true If the event is set.
* @retval false If the event is not set.
*/
__STATIC_INLINE bool nrf_spis_event_check(NRF_SPIS_Type const * p_spis,
nrf_spis_event_t spis_event);
/**
* @brief Function for getting the address of a specific SPIS event register.
*
* @param[in] p_spis SPIS instance.
* @param[in] spis_event Requested event.
*
* @return Address of the specified event register.
*/
__STATIC_INLINE uint32_t nrf_spis_event_address_get(NRF_SPIS_Type const * p_spis,
nrf_spis_event_t spis_event);
/**
* @brief Function for enabling specified shortcuts.
*
* @param[in] p_spis SPIS instance.
* @param[in] spis_shorts_mask Shortcuts to enable.
*/
__STATIC_INLINE void nrf_spis_shorts_enable(NRF_SPIS_Type * p_spis,
uint32_t spis_shorts_mask);
/**
* @brief Function for disabling specified shortcuts.
*
* @param[in] p_spis SPIS instance.
* @param[in] spis_shorts_mask Shortcuts to disable.
*/
__STATIC_INLINE void nrf_spis_shorts_disable(NRF_SPIS_Type * p_spis,
uint32_t spis_shorts_mask);
/**
* @brief Function for enabling specified interrupts.
*
* @param[in] p_spis SPIS instance.
* @param[in] spis_int_mask Interrupts to enable.
*/
__STATIC_INLINE void nrf_spis_int_enable(NRF_SPIS_Type * p_spis,
uint32_t spis_int_mask);
/**
* @brief Function for disabling specified interrupts.
*
* @param[in] p_spis SPIS instance.
* @param[in] spis_int_mask Interrupts to disable.
*/
__STATIC_INLINE void nrf_spis_int_disable(NRF_SPIS_Type * p_spis,
uint32_t spis_int_mask);
/**
* @brief Function for retrieving the state of a given interrupt.
*
* @param[in] p_spis SPIS instance.
* @param[in] spis_int Interrupt to check.
*
* @retval true If the interrupt is enabled.
* @retval false If the interrupt is not enabled.
*/
__STATIC_INLINE bool nrf_spis_int_enable_check(NRF_SPIS_Type const * p_spis,
nrf_spis_int_mask_t spis_int);
/**
* @brief Function for enabling the SPIS peripheral.
*
* @param[in] p_spis SPIS instance.
*/
__STATIC_INLINE void nrf_spis_enable(NRF_SPIS_Type * p_spis);
/**
* @brief Function for disabling the SPIS peripheral.
*
* @param[in] p_spis SPIS instance.
*/
__STATIC_INLINE void nrf_spis_disable(NRF_SPIS_Type * p_spis);
/**
* @brief Function for retrieving the SPIS semaphore status.
*
* @param[in] p_spis SPIS instance.
*
* @returns Current semaphore status.
*/
__STATIC_INLINE nrf_spis_semstat_t nrf_spis_semaphore_status_get(NRF_SPIS_Type * p_spis);
/**
* @brief Function for retrieving the SPIS status.
*
* @param[in] p_spis SPIS instance.
*
* @returns Current SPIS status.
*/
__STATIC_INLINE nrf_spis_status_mask_t nrf_spis_status_get(NRF_SPIS_Type * p_spis);
/**
* @brief Function for configuring SPIS pins.
*
* If a given signal is not needed, pass the @ref NRF_SPIS_PIN_NOT_CONNECTED
* value instead of its pin number.
*
* @param[in] p_spis SPIS instance.
* @param[in] sck_pin SCK pin number.
* @param[in] mosi_pin MOSI pin number.
* @param[in] miso_pin MISO pin number.
* @param[in] csn_pin CSN pin number.
*/
__STATIC_INLINE void nrf_spis_pins_set(NRF_SPIS_Type * p_spis,
uint32_t sck_pin,
uint32_t mosi_pin,
uint32_t miso_pin,
uint32_t csn_pin);
/**
* @brief Function for setting the transmit buffer.
*
* @param[in] p_spis SPIS instance.
* @param[in] p_buffer Pointer to the buffer that contains the data to send.
* @param[in] length Maximum number of data bytes to transmit.
*/
__STATIC_INLINE void nrf_spis_tx_buffer_set(NRF_SPIS_Type * p_spis,
uint8_t const * p_buffer,
uint8_t length);
/**
* @brief Function for setting the receive buffer.
*
* @param[in] p_spis SPIS instance.
* @param[in] p_buffer Pointer to the buffer for received data.
* @param[in] length Maximum number of data bytes to receive.
*/
__STATIC_INLINE void nrf_spis_rx_buffer_set(NRF_SPIS_Type * p_spis,
uint8_t * p_buffer,
uint8_t length);
/**
* @brief Function for getting the number of bytes transmitted
* in the last granted transaction.
*
* @param[in] p_spis SPIS instance.
*
* @returns Number of bytes transmitted.
*/
__STATIC_INLINE uint8_t nrf_spis_tx_amount_get(NRF_SPIS_Type const * p_spis);
/**
* @brief Function for getting the number of bytes received
* in the last granted transaction.
*
* @param[in] p_spis SPIS instance.
*
* @returns Number of bytes received.
*/
__STATIC_INLINE uint8_t nrf_spis_rx_amount_get(NRF_SPIS_Type const * p_spis);
/**
* @brief Function for setting the SPI configuration.
*
* @param[in] p_spis SPIS instance.
* @param[in] spi_mode SPI mode.
* @param[in] spi_bit_order SPI bit order.
*/
__STATIC_INLINE void nrf_spis_configure(NRF_SPIS_Type * p_spis,
nrf_spis_mode_t spi_mode,
nrf_spis_bit_order_t spi_bit_order);
/**
* @brief Function for setting the default character.
*
* @param[in] p_spis SPIS instance.
* @param[in] def Default character that is clocked out in case of
* an overflow of the RXD buffer.
*/
__STATIC_INLINE void nrf_spis_def_set(NRF_SPIS_Type * p_spis,
uint8_t def);
/**
* @brief Function for setting the over-read character.
*
* @param[in] p_spis SPIS instance.
* @param[in] orc Over-read character that is clocked out in case of
* an over-read of the TXD buffer.
*/
__STATIC_INLINE void nrf_spis_orc_set(NRF_SPIS_Type * p_spis,
uint8_t orc);
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE void nrf_spis_task_trigger(NRF_SPIS_Type * p_spis,
nrf_spis_task_t spis_task)
{
*((volatile uint32_t *)((uint8_t *)p_spis + (uint32_t)spis_task)) = 0x1UL;
}
__STATIC_INLINE uint32_t nrf_spis_task_address_get(NRF_SPIS_Type const * p_spis,
nrf_spis_task_t spis_task)
{
return (uint32_t)p_spis + (uint32_t)spis_task;
}
__STATIC_INLINE void nrf_spis_event_clear(NRF_SPIS_Type * p_spis,
nrf_spis_event_t spis_event)
{
*((volatile uint32_t *)((uint8_t *)p_spis + (uint32_t)spis_event)) = 0x0UL;
}
__STATIC_INLINE bool nrf_spis_event_check(NRF_SPIS_Type const * p_spis,
nrf_spis_event_t spis_event)
{
return (bool)*(volatile uint32_t *)((uint8_t *)p_spis + (uint32_t)spis_event);
}
__STATIC_INLINE uint32_t nrf_spis_event_address_get(NRF_SPIS_Type const * p_spis,
nrf_spis_event_t spis_event)
{
return (uint32_t)p_spis + (uint32_t)spis_event;
}
__STATIC_INLINE void nrf_spis_shorts_enable(NRF_SPIS_Type * p_spis,
uint32_t spis_shorts_mask)
{
p_spis->SHORTS |= spis_shorts_mask;
}
__STATIC_INLINE void nrf_spis_shorts_disable(NRF_SPIS_Type * p_spis,
uint32_t spis_shorts_mask)
{
p_spis->SHORTS &= ~(spis_shorts_mask);
}
__STATIC_INLINE void nrf_spis_int_enable(NRF_SPIS_Type * p_spis,
uint32_t spis_int_mask)
{
p_spis->INTENSET = spis_int_mask;
}
__STATIC_INLINE void nrf_spis_int_disable(NRF_SPIS_Type * p_spis,
uint32_t spis_int_mask)
{
p_spis->INTENCLR = spis_int_mask;
}
__STATIC_INLINE bool nrf_spis_int_enable_check(NRF_SPIS_Type const * p_spis,
nrf_spis_int_mask_t spis_int)
{
return (bool)(p_spis->INTENSET & spis_int);
}
__STATIC_INLINE void nrf_spis_enable(NRF_SPIS_Type * p_spis)
{
p_spis->ENABLE = (SPIS_ENABLE_ENABLE_Enabled << SPIS_ENABLE_ENABLE_Pos);
}
__STATIC_INLINE void nrf_spis_disable(NRF_SPIS_Type * p_spis)
{
p_spis->ENABLE = (SPIS_ENABLE_ENABLE_Disabled << SPIS_ENABLE_ENABLE_Pos);
}
__STATIC_INLINE nrf_spis_semstat_t nrf_spis_semaphore_status_get(NRF_SPIS_Type * p_spis)
{
return (nrf_spis_semstat_t) ((p_spis->SEMSTAT & SPIS_SEMSTAT_SEMSTAT_Msk)
>> SPIS_SEMSTAT_SEMSTAT_Pos);
}
__STATIC_INLINE nrf_spis_status_mask_t nrf_spis_status_get(NRF_SPIS_Type * p_spis)
{
return (nrf_spis_status_mask_t) p_spis->STATUS;
}
__STATIC_INLINE void nrf_spis_pins_set(NRF_SPIS_Type * p_spis,
uint32_t sck_pin,
uint32_t mosi_pin,
uint32_t miso_pin,
uint32_t csn_pin)
{
p_spis->PSELSCK = sck_pin;
p_spis->PSELMOSI = mosi_pin;
p_spis->PSELMISO = miso_pin;
p_spis->PSELCSN = csn_pin;
}
__STATIC_INLINE void nrf_spis_tx_buffer_set(NRF_SPIS_Type * p_spis,
uint8_t const * p_buffer,
uint8_t length)
{
p_spis->TXDPTR = (uint32_t)p_buffer;
p_spis->MAXTX = length;
}
__STATIC_INLINE void nrf_spis_rx_buffer_set(NRF_SPIS_Type * p_spis,
uint8_t * p_buffer,
uint8_t length)
{
p_spis->RXDPTR = (uint32_t)p_buffer;
p_spis->MAXRX = length;
}
__STATIC_INLINE uint8_t nrf_spis_tx_amount_get(NRF_SPIS_Type const * p_spis)
{
return (uint8_t) p_spis->AMOUNTRX;
}
__STATIC_INLINE uint8_t nrf_spis_rx_amount_get(NRF_SPIS_Type const * p_spis)
{
return (uint8_t) p_spis->AMOUNTTX;
}
__STATIC_INLINE void nrf_spis_configure(NRF_SPIS_Type * p_spis,
nrf_spis_mode_t spi_mode,
nrf_spis_bit_order_t spi_bit_order)
{
uint32_t config = (spi_bit_order == NRF_SPIS_BIT_ORDER_MSB_FIRST ?
SPIS_CONFIG_ORDER_MsbFirst : SPIS_CONFIG_ORDER_LsbFirst);
switch (spi_mode)
{
default:
case NRF_SPIS_MODE_0:
config |= (SPIS_CONFIG_CPOL_ActiveHigh << SPIS_CONFIG_CPOL_Pos) |
(SPIS_CONFIG_CPHA_Leading << SPIS_CONFIG_CPHA_Pos);
break;
case NRF_SPIS_MODE_1:
config |= (SPIS_CONFIG_CPOL_ActiveHigh << SPIS_CONFIG_CPOL_Pos) |
(SPIS_CONFIG_CPHA_Trailing << SPIS_CONFIG_CPHA_Pos);
break;
case NRF_SPIS_MODE_2:
config |= (SPIS_CONFIG_CPOL_ActiveLow << SPIS_CONFIG_CPOL_Pos) |
(SPIS_CONFIG_CPHA_Leading << SPIS_CONFIG_CPHA_Pos);
break;
case NRF_SPIS_MODE_3:
config |= (SPIS_CONFIG_CPOL_ActiveLow << SPIS_CONFIG_CPOL_Pos) |
(SPIS_CONFIG_CPHA_Trailing << SPIS_CONFIG_CPHA_Pos);
break;
}
p_spis->CONFIG = config;
}
__STATIC_INLINE void nrf_spis_orc_set(NRF_SPIS_Type * p_spis,
uint8_t orc)
{
p_spis->ORC = orc;
}
__STATIC_INLINE void nrf_spis_def_set(NRF_SPIS_Type * p_spis,
uint8_t def)
{
p_spis->DEF = def;
}
#endif // SUPPRESS_INLINE_IMPLEMENTATION
#endif // NRF_SPIS_H__
/** @} */

View File

@ -1,82 +0,0 @@
/*
* Copyright (c) 2012 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_TEMP_H__
#define NRF_TEMP_H__
#include "nrf.h"
/**
* @defgroup nrf_temperature TEMP (temperature) abstraction
* @{
* @ingroup nrf_drivers temperature_example
* @brief Temperature module init and read functions.
*
*/
/**@cond NO_DOXYGEN */
#define MASK_SIGN (0x00000200UL)
#define MASK_SIGN_EXTENSION (0xFFFFFC00UL)
/**
* @brief Function for preparing the temp module for temperature measurement.
*
* This function initializes the TEMP module and writes to the hidden configuration register.
*/
static __INLINE void nrf_temp_init(void)
{
/**@note Workaround for PAN_028 rev2.0A anomaly 31 - TEMP: Temperature offset value has to be manually loaded to the TEMP module */
*(uint32_t *) 0x4000C504 = 0;
}
/**
* @brief Function for reading temperature measurement.
*
* The function reads the 10 bit 2's complement value and transforms it to a 32 bit 2's complement value.
*/
static __INLINE int32_t nrf_temp_read(void)
{
/**@note Workaround for PAN_028 rev2.0A anomaly 28 - TEMP: Negative measured values are not represented correctly */
return ((NRF_TEMP->TEMP & MASK_SIGN) != 0) ? (NRF_TEMP->TEMP | MASK_SIGN_EXTENSION) : (NRF_TEMP->TEMP);
}
/**@endcond */
/** @} */
#endif

View File

@ -1,603 +0,0 @@
/*
* Copyright (c) 2014 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_timer_hal Timer HAL
* @{
* @ingroup nrf_timer
*
* @brief Hardware access layer for accessing the timer peripheral.
*/
#ifndef NRF_TIMER_H__
#define NRF_TIMER_H__
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "nrf.h"
#include "nrf_assert.h"
/**
* @brief Macro for validating the correctness of the BIT_WIDTH setting.
*/
#ifdef NRF51
/**
* In the nRF51 Series, timer instance 0 supports all available bit widths.
* The other two instances support only 8 and 16 bits.
*/
#define NRF_TIMER_IS_BIT_WIDTH_VALID(p_timer, bit_width) \
((p_timer == NRF_TIMER0) || (bit_width <= NRF_TIMER_BIT_WIDTH_16))
#else
/**
* In the nRF52 Series, all timer instances support all available bit widths.
*/
#define NRF_TIMER_IS_BIT_WIDTH_VALID(p_timer, bit_width) true
#endif
/**
* @brief Macro for getting the number of capture/compare channels available
* in a given timer instance.
*/
#ifdef NRF51
#define NRF_TIMER_CC_CHANNEL_COUNT(id) 4
#else
#define NRF_TIMER_CC_CHANNEL_COUNT(id) ((id) <= 2 ? 4 : 6)
#endif
/**
* @brief Timer tasks.
*/
typedef enum
{
/*lint -save -e30 -esym(628,__INTADDR__)*/
NRF_TIMER_TASK_START = offsetof(NRF_TIMER_Type, TASKS_START), ///< Task for starting the timer.
NRF_TIMER_TASK_STOP = offsetof(NRF_TIMER_Type, TASKS_STOP), ///< Task for stopping the timer.
NRF_TIMER_TASK_COUNT = offsetof(NRF_TIMER_Type, TASKS_COUNT), ///< Task for incrementing the timer (in counter mode).
NRF_TIMER_TASK_CLEAR = offsetof(NRF_TIMER_Type, TASKS_CLEAR), ///< Task for resetting the timer value.
NRF_TIMER_TASK_SHUTDOWN = offsetof(NRF_TIMER_Type, TASKS_SHUTDOWN), ///< Task for powering off the timer.
NRF_TIMER_TASK_CAPTURE0 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[0]), ///< Task for capturing the timer value on channel 0.
NRF_TIMER_TASK_CAPTURE1 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[1]), ///< Task for capturing the timer value on channel 1.
NRF_TIMER_TASK_CAPTURE2 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[2]), ///< Task for capturing the timer value on channel 2.
NRF_TIMER_TASK_CAPTURE3 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[3]), ///< Task for capturing the timer value on channel 3.
#ifdef NRF52
NRF_TIMER_TASK_CAPTURE4 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[4]), ///< Task for capturing the timer value on channel 4.
NRF_TIMER_TASK_CAPTURE5 = offsetof(NRF_TIMER_Type, TASKS_CAPTURE[5]), ///< Task for capturing the timer value on channel 5.
#endif
/*lint -restore*/
} nrf_timer_task_t;
/**
* @brief Timer events.
*/
typedef enum
{
/*lint -save -e30*/
NRF_TIMER_EVENT_COMPARE0 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[0]), ///< Event from compare channel 0.
NRF_TIMER_EVENT_COMPARE1 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[1]), ///< Event from compare channel 1.
NRF_TIMER_EVENT_COMPARE2 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[2]), ///< Event from compare channel 2.
NRF_TIMER_EVENT_COMPARE3 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[3]), ///< Event from compare channel 3.
#ifdef NRF52
NRF_TIMER_EVENT_COMPARE4 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[4]), ///< Event from compare channel 4.
NRF_TIMER_EVENT_COMPARE5 = offsetof(NRF_TIMER_Type, EVENTS_COMPARE[5]), ///< Event from compare channel 5.
#endif
/*lint -restore*/
} nrf_timer_event_t;
/**
* @brief Types of timer shortcuts.
*/
typedef enum
{
NRF_TIMER_SHORT_COMPARE0_STOP_MASK = TIMER_SHORTS_COMPARE0_STOP_Msk, ///< Shortcut for stopping the timer based on compare 0.
NRF_TIMER_SHORT_COMPARE1_STOP_MASK = TIMER_SHORTS_COMPARE1_STOP_Msk, ///< Shortcut for stopping the timer based on compare 1.
NRF_TIMER_SHORT_COMPARE2_STOP_MASK = TIMER_SHORTS_COMPARE2_STOP_Msk, ///< Shortcut for stopping the timer based on compare 2.
NRF_TIMER_SHORT_COMPARE3_STOP_MASK = TIMER_SHORTS_COMPARE3_STOP_Msk, ///< Shortcut for stopping the timer based on compare 3.
#ifdef NRF52
NRF_TIMER_SHORT_COMPARE4_STOP_MASK = TIMER_SHORTS_COMPARE4_STOP_Msk, ///< Shortcut for stopping the timer based on compare 4.
NRF_TIMER_SHORT_COMPARE5_STOP_MASK = TIMER_SHORTS_COMPARE5_STOP_Msk, ///< Shortcut for stopping the timer based on compare 5.
#endif
NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK = TIMER_SHORTS_COMPARE0_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 0.
NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK = TIMER_SHORTS_COMPARE1_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 1.
NRF_TIMER_SHORT_COMPARE2_CLEAR_MASK = TIMER_SHORTS_COMPARE2_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 2.
NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK = TIMER_SHORTS_COMPARE3_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 3.
#ifdef NRF52
NRF_TIMER_SHORT_COMPARE4_CLEAR_MASK = TIMER_SHORTS_COMPARE4_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 4.
NRF_TIMER_SHORT_COMPARE5_CLEAR_MASK = TIMER_SHORTS_COMPARE5_CLEAR_Msk, ///< Shortcut for clearing the timer based on compare 5.
#endif
} nrf_timer_short_mask_t;
/**
* @brief Timer modes.
*/
typedef enum
{
NRF_TIMER_MODE_TIMER = TIMER_MODE_MODE_Timer, ///< Timer mode: timer.
NRF_TIMER_MODE_COUNTER = TIMER_MODE_MODE_Counter, ///< Timer mode: counter.
#ifdef NRF52
NRF_TIMER_MODE_LOW_POWER_COUNTER = TIMER_MODE_MODE_LowPowerCounter, ///< Timer mode: low-power counter.
#endif
} nrf_timer_mode_t;
/**
* @brief Timer bit width.
*/
typedef enum
{
NRF_TIMER_BIT_WIDTH_8 = TIMER_BITMODE_BITMODE_08Bit, ///< Timer bit width 8 bit.
NRF_TIMER_BIT_WIDTH_16 = TIMER_BITMODE_BITMODE_16Bit, ///< Timer bit width 16 bit.
NRF_TIMER_BIT_WIDTH_24 = TIMER_BITMODE_BITMODE_24Bit, ///< Timer bit width 24 bit.
NRF_TIMER_BIT_WIDTH_32 = TIMER_BITMODE_BITMODE_32Bit ///< Timer bit width 32 bit.
} nrf_timer_bit_width_t;
/**
* @brief Timer prescalers.
*/
typedef enum
{
NRF_TIMER_FREQ_16MHz = 0, ///< Timer frequency 16 MHz.
NRF_TIMER_FREQ_8MHz, ///< Timer frequency 8 MHz.
NRF_TIMER_FREQ_4MHz, ///< Timer frequency 4 MHz.
NRF_TIMER_FREQ_2MHz, ///< Timer frequency 2 MHz.
NRF_TIMER_FREQ_1MHz, ///< Timer frequency 1 MHz.
NRF_TIMER_FREQ_500kHz, ///< Timer frequency 500 kHz.
NRF_TIMER_FREQ_250kHz, ///< Timer frequency 250 kHz.
NRF_TIMER_FREQ_125kHz, ///< Timer frequency 125 kHz.
NRF_TIMER_FREQ_62500Hz, ///< Timer frequency 62500 Hz.
NRF_TIMER_FREQ_31250Hz ///< Timer frequency 31250 Hz.
} nrf_timer_frequency_t;
/**
* @brief Timer capture/compare channels.
*/
typedef enum
{
NRF_TIMER_CC_CHANNEL0 = 0, ///< Timer capture/compare channel 0.
NRF_TIMER_CC_CHANNEL1, ///< Timer capture/compare channel 1.
NRF_TIMER_CC_CHANNEL2, ///< Timer capture/compare channel 2.
NRF_TIMER_CC_CHANNEL3, ///< Timer capture/compare channel 3.
#ifdef NRF52
NRF_TIMER_CC_CHANNEL4, ///< Timer capture/compare channel 4.
NRF_TIMER_CC_CHANNEL5, ///< Timer capture/compare channel 5.
#endif
} nrf_timer_cc_channel_t;
/**
* @brief Timer interrupts.
*/
typedef enum
{
NRF_TIMER_INT_COMPARE0_MASK = TIMER_INTENSET_COMPARE0_Msk, ///< Timer interrupt from compare event on channel 0.
NRF_TIMER_INT_COMPARE1_MASK = TIMER_INTENSET_COMPARE1_Msk, ///< Timer interrupt from compare event on channel 1.
NRF_TIMER_INT_COMPARE2_MASK = TIMER_INTENSET_COMPARE2_Msk, ///< Timer interrupt from compare event on channel 2.
NRF_TIMER_INT_COMPARE3_MASK = TIMER_INTENSET_COMPARE3_Msk, ///< Timer interrupt from compare event on channel 3.
#ifdef NRF52
NRF_TIMER_INT_COMPARE4_MASK = TIMER_INTENSET_COMPARE4_Msk, ///< Timer interrupt from compare event on channel 4.
NRF_TIMER_INT_COMPARE5_MASK = TIMER_INTENSET_COMPARE5_Msk, ///< Timer interrupt from compare event on channel 5.
#endif
} nrf_timer_int_mask_t;
/**
* @brief Function for activating a specific timer task.
*
* @param[in] p_timer Timer instance.
* @param[in] task Task to activate.
*/
__STATIC_INLINE void nrf_timer_task_trigger(NRF_TIMER_Type * p_timer,
nrf_timer_task_t task);
/**
* @brief Function for getting the address of a specific timer task register.
*
* @param[in] p_timer Timer instance.
* @param[in] task Requested task.
*
* @return Address of the specified task register.
*/
__STATIC_INLINE uint32_t * nrf_timer_task_address_get(NRF_TIMER_Type * p_timer,
nrf_timer_task_t task);
/**
* @brief Function for clearing a specific timer event.
*
* @param[in] p_timer Timer instance.
* @param[in] event Event to clear.
*/
__STATIC_INLINE void nrf_timer_event_clear(NRF_TIMER_Type * p_timer,
nrf_timer_event_t event);
/**
* @brief Function for checking the state of a specific timer event.
*
* @param[in] p_timer Timer instance.
* @param[in] event Event to check.
*
* @retval true If the event is set.
* @retval false If the event is not set.
*/
__STATIC_INLINE bool nrf_timer_event_check(NRF_TIMER_Type * p_timer,
nrf_timer_event_t event);
/**
* @brief Function for getting the address of a specific timer event register.
*
* @param[in] p_timer Timer instance.
* @param[in] event Requested event.
*
* @return Address of the specified event register.
*/
__STATIC_INLINE uint32_t * nrf_timer_event_address_get(NRF_TIMER_Type * p_timer,
nrf_timer_event_t event);
/**
* @brief Function for enabling specified shortcuts.
*
* @param[in] p_timer Timer instance.
* @param[in] timer_shorts_mask Shortcuts to enable.
*/
__STATIC_INLINE void nrf_timer_shorts_enable(NRF_TIMER_Type * p_timer,
uint32_t timer_shorts_mask);
/**
* @brief Function for disabling specified shortcuts.
*
* @param[in] p_timer Timer instance.
* @param[in] timer_shorts_mask Shortcuts to disable.
*/
__STATIC_INLINE void nrf_timer_shorts_disable(NRF_TIMER_Type * p_timer,
uint32_t timer_shorts_mask);
/**
* @brief Function for enabling specified interrupts.
*
* @param[in] p_timer Timer instance.
* @param[in] timer_int_mask Interrupts to enable.
*/
__STATIC_INLINE void nrf_timer_int_enable(NRF_TIMER_Type * p_timer,
uint32_t timer_int_mask);
/**
* @brief Function for disabling specified interrupts.
*
* @param[in] p_timer Timer instance.
* @param[in] timer_int_mask Interrupts to disable.
*/
__STATIC_INLINE void nrf_timer_int_disable(NRF_TIMER_Type * p_timer,
uint32_t timer_int_mask);
/**
* @brief Function for retrieving the state of a given interrupt.
*
* @param[in] p_timer Timer instance.
* @param[in] timer_int Interrupt to check.
*
* @retval true If the interrupt is enabled.
* @retval false If the interrupt is not enabled.
*/
__STATIC_INLINE bool nrf_timer_int_enable_check(NRF_TIMER_Type * p_timer,
uint32_t timer_int);
/**
* @brief Function for setting the timer mode.
*
* @param[in] p_timer Timer instance.
* @param[in] mode Timer mode.
*/
__STATIC_INLINE void nrf_timer_mode_set(NRF_TIMER_Type * p_timer,
nrf_timer_mode_t mode);
/**
* @brief Function for retrieving the timer mode.
*
* @param[in] p_timer Timer instance.
*
* @return Timer mode.
*/
__STATIC_INLINE nrf_timer_mode_t nrf_timer_mode_get(NRF_TIMER_Type * p_timer);
/**
* @brief Function for setting the timer bit width.
*
* @param[in] p_timer Timer instance.
* @param[in] bit_width Timer bit width.
*/
__STATIC_INLINE void nrf_timer_bit_width_set(NRF_TIMER_Type * p_timer,
nrf_timer_bit_width_t bit_width);
/**
* @brief Function for retrieving the timer bit width.
*
* @param[in] p_timer Timer instance.
*
* @return Timer bit width.
*/
__STATIC_INLINE nrf_timer_bit_width_t nrf_timer_bit_width_get(NRF_TIMER_Type * p_timer);
/**
* @brief Function for setting the timer frequency.
*
* @param[in] p_timer Timer instance.
* @param[in] frequency Timer frequency.
*/
__STATIC_INLINE void nrf_timer_frequency_set(NRF_TIMER_Type * p_timer,
nrf_timer_frequency_t frequency);
/**
* @brief Function for retrieving the timer frequency.
*
* @param[in] p_timer Timer instance.
*
* @return Timer frequency.
*/
__STATIC_INLINE nrf_timer_frequency_t nrf_timer_frequency_get(NRF_TIMER_Type * p_timer);
/**
* @brief Function for writing the capture/compare register for a specified channel.
*
* @param[in] p_timer Timer instance.
* @param[in] cc_channel Requested capture/compare channel.
* @param[in] cc_value Value to write to the capture/compare register.
*/
__STATIC_INLINE void nrf_timer_cc_write(NRF_TIMER_Type * p_timer,
nrf_timer_cc_channel_t cc_channel,
uint32_t cc_value);
/**
* @brief Function for retrieving the capture/compare value for a specified channel.
*
* @param[in] p_timer Timer instance.
* @param[in] cc_channel Requested capture/compare channel.
*
* @return Value from the requested capture/compare register.
*/
__STATIC_INLINE uint32_t nrf_timer_cc_read(NRF_TIMER_Type * p_timer,
nrf_timer_cc_channel_t cc_channel);
/**
* @brief Function for getting a specific timer capture task.
*
* @param[in] channel Capture channel.
*
* @return Capture task.
*/
__STATIC_INLINE nrf_timer_task_t nrf_timer_capture_task_get(uint32_t channel);
/**
* @brief Function for getting a specific timer compare event.
*
* @param[in] channel Compare channel.
*
* @return Compare event.
*/
__STATIC_INLINE nrf_timer_event_t nrf_timer_compare_event_get(uint32_t channel);
/**
* @brief Function for getting a specific timer compare interrupt.
*
* @param[in] channel Compare channel.
*
* @return Compare interrupt.
*/
__STATIC_INLINE nrf_timer_int_mask_t nrf_timer_compare_int_get(uint32_t channel);
/**
* @brief Function for calculating the number of timer ticks for a given time
* (in microseconds) and timer frequency.
*
* @param[in] time_us Time in microseconds.
* @param[in] frequency Timer frequency.
*
* @return Number of timer ticks.
*/
__STATIC_INLINE uint32_t nrf_timer_us_to_ticks(uint32_t time_us,
nrf_timer_frequency_t frequency);
/**
* @brief Function for calculating the number of timer ticks for a given time
* (in milliseconds) and timer frequency.
*
* @param[in] time_ms Time in milliseconds.
* @param[in] frequency Timer frequency.
*
* @return Number of timer ticks.
*/
__STATIC_INLINE uint32_t nrf_timer_ms_to_ticks(uint32_t time_ms,
nrf_timer_frequency_t frequency);
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE void nrf_timer_task_trigger(NRF_TIMER_Type * p_timer,
nrf_timer_task_t task)
{
*((volatile uint32_t *)((uint8_t *)p_timer + (uint32_t)task)) = 0x1UL;
}
__STATIC_INLINE uint32_t * nrf_timer_task_address_get(NRF_TIMER_Type * p_timer,
nrf_timer_task_t task)
{
return (uint32_t *)((uint8_t *)p_timer + (uint32_t)task);
}
__STATIC_INLINE void nrf_timer_event_clear(NRF_TIMER_Type * p_timer,
nrf_timer_event_t event)
{
*((volatile uint32_t *)((uint8_t *)p_timer + (uint32_t)event)) = 0x0UL;
}
__STATIC_INLINE bool nrf_timer_event_check(NRF_TIMER_Type * p_timer,
nrf_timer_event_t event)
{
return (bool)*(volatile uint32_t *)((uint8_t *)p_timer + (uint32_t)event);
}
__STATIC_INLINE uint32_t * nrf_timer_event_address_get(NRF_TIMER_Type * p_timer,
nrf_timer_event_t event)
{
return (uint32_t *)((uint8_t *)p_timer + (uint32_t)event);
}
__STATIC_INLINE void nrf_timer_shorts_enable(NRF_TIMER_Type * p_timer,
uint32_t timer_shorts_mask)
{
p_timer->SHORTS |= timer_shorts_mask;
}
__STATIC_INLINE void nrf_timer_shorts_disable(NRF_TIMER_Type * p_timer,
uint32_t timer_shorts_mask)
{
p_timer->SHORTS &= ~(timer_shorts_mask);
}
__STATIC_INLINE void nrf_timer_int_enable(NRF_TIMER_Type * p_timer,
uint32_t timer_int_mask)
{
p_timer->INTENSET = timer_int_mask;
}
__STATIC_INLINE void nrf_timer_int_disable(NRF_TIMER_Type * p_timer,
uint32_t timer_int_mask)
{
p_timer->INTENCLR = timer_int_mask;
}
__STATIC_INLINE bool nrf_timer_int_enable_check(NRF_TIMER_Type * p_timer,
uint32_t timer_int)
{
return (bool)(p_timer->INTENSET & timer_int);
}
__STATIC_INLINE void nrf_timer_mode_set(NRF_TIMER_Type * p_timer,
nrf_timer_mode_t mode)
{
p_timer->MODE = (p_timer->MODE & ~TIMER_MODE_MODE_Msk) |
((mode << TIMER_MODE_MODE_Pos) & TIMER_MODE_MODE_Msk);
}
__STATIC_INLINE nrf_timer_mode_t nrf_timer_mode_get(NRF_TIMER_Type * p_timer)
{
return (nrf_timer_mode_t)(p_timer->MODE);
}
__STATIC_INLINE void nrf_timer_bit_width_set(NRF_TIMER_Type * p_timer,
nrf_timer_bit_width_t bit_width)
{
p_timer->BITMODE = (p_timer->BITMODE & ~TIMER_BITMODE_BITMODE_Msk) |
((bit_width << TIMER_BITMODE_BITMODE_Pos) &
TIMER_BITMODE_BITMODE_Msk);
}
__STATIC_INLINE nrf_timer_bit_width_t nrf_timer_bit_width_get(NRF_TIMER_Type * p_timer)
{
return (nrf_timer_bit_width_t)(p_timer->BITMODE);
}
__STATIC_INLINE void nrf_timer_frequency_set(NRF_TIMER_Type * p_timer,
nrf_timer_frequency_t frequency)
{
p_timer->PRESCALER = (p_timer->PRESCALER & ~TIMER_PRESCALER_PRESCALER_Msk) |
((frequency << TIMER_PRESCALER_PRESCALER_Pos) &
TIMER_PRESCALER_PRESCALER_Msk);
}
__STATIC_INLINE nrf_timer_frequency_t nrf_timer_frequency_get(NRF_TIMER_Type * p_timer)
{
return (nrf_timer_frequency_t)(p_timer->PRESCALER);
}
__STATIC_INLINE void nrf_timer_cc_write(NRF_TIMER_Type * p_timer,
nrf_timer_cc_channel_t cc_channel,
uint32_t cc_value)
{
p_timer->CC[cc_channel] = cc_value;
}
__STATIC_INLINE uint32_t nrf_timer_cc_read(NRF_TIMER_Type * p_timer,
nrf_timer_cc_channel_t cc_channel)
{
return (uint32_t)p_timer->CC[cc_channel];
}
__STATIC_INLINE nrf_timer_task_t nrf_timer_capture_task_get(uint32_t channel)
{
return (nrf_timer_task_t)
((uint32_t)NRF_TIMER_TASK_CAPTURE0 + (channel * sizeof(uint32_t)));
}
__STATIC_INLINE nrf_timer_event_t nrf_timer_compare_event_get(uint32_t channel)
{
return (nrf_timer_event_t)
((uint32_t)NRF_TIMER_EVENT_COMPARE0 + (channel * sizeof(uint32_t)));
}
__STATIC_INLINE nrf_timer_int_mask_t nrf_timer_compare_int_get(uint32_t channel)
{
return (nrf_timer_int_mask_t)
((uint32_t)NRF_TIMER_INT_COMPARE0_MASK << channel);
}
__STATIC_INLINE uint32_t nrf_timer_us_to_ticks(uint32_t time_us,
nrf_timer_frequency_t frequency)
{
// The "frequency" parameter here is actually the prescaler value, and the
// timer runs at the following frequency: f = 16 MHz / 2^prescaler.
uint32_t prescaler = (uint32_t)frequency;
ASSERT(time_us <= (UINT32_MAX / 16UL));
return ((time_us * 16UL) >> prescaler);
}
__STATIC_INLINE uint32_t nrf_timer_ms_to_ticks(uint32_t time_ms,
nrf_timer_frequency_t frequency)
{
// The "frequency" parameter here is actually the prescaler value, and the
// timer runs at the following frequency: f = 16000 kHz / 2^prescaler.
uint32_t prescaler = (uint32_t)frequency;
ASSERT(time_ms <= (UINT32_MAX / 16000UL));
return ((time_ms * 16000UL) >> prescaler);
}
#endif // SUPPRESS_INLINE_IMPLEMENTATION
#endif // NRF_TIMER_H__
/** @} */

View File

@ -1,429 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_H__
#define NRF_TWI_H__
/**
* @defgroup nrf_twi_hal TWI HAL
* @{
* @ingroup nrf_twi_master
*
* @brief Hardware access layer for managing the TWI peripheral.
*/
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include "nrf.h"
/**
* @brief TWI tasks.
*/
typedef enum
{
/*lint -save -e30*/
NRF_TWI_TASK_STARTRX = offsetof(NRF_TWI_Type, TASKS_STARTRX), ///< Start TWI receive sequence.
NRF_TWI_TASK_STARTTX = offsetof(NRF_TWI_Type, TASKS_STARTTX), ///< Start TWI transmit sequence.
NRF_TWI_TASK_STOP = offsetof(NRF_TWI_Type, TASKS_STOP), ///< Stop TWI transaction.
NRF_TWI_TASK_SUSPEND = offsetof(NRF_TWI_Type, TASKS_SUSPEND), ///< Suspend TWI transaction.
NRF_TWI_TASK_RESUME = offsetof(NRF_TWI_Type, TASKS_RESUME) ///< Resume TWI transaction.
/*lint -restore*/
} nrf_twi_task_t;
/**
* @brief TWI events.
*/
typedef enum
{
/*lint -save -e30*/
NRF_TWI_EVENT_STOPPED = offsetof(NRF_TWI_Type, EVENTS_STOPPED), ///< TWI stopped.
NRF_TWI_EVENT_RXDREADY = offsetof(NRF_TWI_Type, EVENTS_RXDREADY), ///< TWI RXD byte received.
NRF_TWI_EVENT_TXDSENT = offsetof(NRF_TWI_Type, EVENTS_TXDSENT), ///< TWI TXD byte sent.
NRF_TWI_EVENT_ERROR = offsetof(NRF_TWI_Type, EVENTS_ERROR), ///< TWI error.
NRF_TWI_EVENT_BB = offsetof(NRF_TWI_Type, EVENTS_BB), ///< TWI byte boundary, generated before each byte that is sent or received.
NRF_TWI_EVENT_SUSPENDED = offsetof(NRF_TWI_Type, EVENTS_SUSPENDED) ///< TWI entered the suspended state.
/*lint -restore*/
} nrf_twi_event_t;
/**
* @brief TWI shortcuts.
*/
typedef enum
{
NRF_TWI_SHORT_BB_SUSPEND_MASK = TWI_SHORTS_BB_SUSPEND_Msk, ///< Shortcut between BB event and SUSPEND task.
NRF_TWI_SHORT_BB_STOP_MASK = TWI_SHORTS_BB_STOP_Msk, ///< Shortcut between BB event and STOP task.
} nrf_twi_short_mask_t;
/**
* @brief TWI interrupts.
*/
typedef enum
{
NRF_TWI_INT_STOPPED_MASK = TWI_INTENSET_STOPPED_Msk, ///< Interrupt on STOPPED event.
NRF_TWI_INT_RXDREADY_MASK = TWI_INTENSET_RXDREADY_Msk, ///< Interrupt on RXDREADY event.
NRF_TWI_INT_TXDSENT_MASK = TWI_INTENSET_TXDSENT_Msk, ///< Interrupt on TXDSENT event.
NRF_TWI_INT_ERROR_MASK = TWI_INTENSET_ERROR_Msk, ///< Interrupt on ERROR event.
NRF_TWI_INT_BB_MASK = TWI_INTENSET_BB_Msk, ///< Interrupt on BB event.
NRF_TWI_INT_SUSPENDED_MASK = TWI_INTENSET_SUSPENDED_Msk ///< Interrupt on SUSPENDED event.
} nrf_twi_int_mask_t;
/**
* @brief TWI error source.
*/
typedef enum
{
NRF_TWI_ERROR_ADDRESS_NACK = TWI_ERRORSRC_ANACK_Msk, ///< NACK received after sending the address.
NRF_TWI_ERROR_DATA_NACK = TWI_ERRORSRC_DNACK_Msk, ///< NACK received after sending a data byte.
NRF_TWI_ERROR_OVERRUN = TWI_ERRORSRC_OVERRUN_Msk ///< Overrun error.
/**< A new byte was received before the previous byte was read
* from the RXD register (previous data is lost). */
} nrf_twi_error_t;
/**
* @brief TWI master clock frequency.
*/
typedef enum
{
NRF_TWI_FREQ_100K = TWI_FREQUENCY_FREQUENCY_K100, ///< 100 kbps.
NRF_TWI_FREQ_250K = TWI_FREQUENCY_FREQUENCY_K250, ///< 250 kbps.
NRF_TWI_FREQ_400K = TWI_FREQUENCY_FREQUENCY_K400 ///< 400 kbps.
} nrf_twi_frequency_t;
/**
* @brief Function for activating a specific TWI task.
*
* @param[in] p_twi TWI instance.
* @param[in] task Task to activate.
*/
__STATIC_INLINE void nrf_twi_task_trigger(NRF_TWI_Type * p_twi,
nrf_twi_task_t task);
/**
* @brief Function for getting the address of a specific TWI task register.
*
* @param[in] p_twi TWI instance.
* @param[in] task Requested task.
*
* @return Address of the specified task register.
*/
__STATIC_INLINE uint32_t * nrf_twi_task_address_get(NRF_TWI_Type * p_twi,
nrf_twi_task_t task);
/**
* @brief Function for clearing a specific TWI event.
*
* @param[in] p_twi TWI instance.
* @param[in] event Event to clear.
*/
__STATIC_INLINE void nrf_twi_event_clear(NRF_TWI_Type * p_twi,
nrf_twi_event_t event);
/**
* @brief Function for checking the state of a specific event.
*
* @param[in] p_twi TWI instance.
* @param[in] event Event to check.
*
* @retval true If the event is set.
* @retval false If the event is not set.
*/
__STATIC_INLINE bool nrf_twi_event_check(NRF_TWI_Type * p_twi,
nrf_twi_event_t event);
/**
* @brief Function for getting the address of a specific TWI event register.
*
* @param[in] p_twi TWI instance.
* @param[in] event Requested event.
*
* @return Address of the specified event register.
*/
__STATIC_INLINE uint32_t * nrf_twi_event_address_get(NRF_TWI_Type * p_twi,
nrf_twi_event_t event);
/**
* @brief Function for enabling specified shortcuts.
*
* @param[in] p_twi TWI instance.
* @param[in] shorts_mask Shortcuts to enable.
*/
__STATIC_INLINE void nrf_twi_shorts_enable(NRF_TWI_Type * p_twi,
uint32_t shorts_mask);
/**
* @brief Function for disabling specified shortcuts.
*
* @param[in] p_twi TWI instance.
* @param[in] shorts_mask Shortcuts to disable.
*/
__STATIC_INLINE void nrf_twi_shorts_disable(NRF_TWI_Type * p_twi,
uint32_t shorts_mask);
/**
* @brief Function for enabling specified interrupts.
*
* @param[in] p_twi TWI instance.
* @param[in] int_mask Interrupts to enable.
*/
__STATIC_INLINE void nrf_twi_int_enable(NRF_TWI_Type * p_twi,
uint32_t int_mask);
/**
* @brief Function for disabling specified interrupts.
*
* @param[in] p_twi TWI instance.
* @param[in] int_mask Interrupts to disable.
*/
__STATIC_INLINE void nrf_twi_int_disable(NRF_TWI_Type * p_twi,
uint32_t int_mask);
/**
* @brief Function for retrieving the state of a given interrupt.
*
* @param[in] p_twi TWI instance.
* @param[in] int_mask Interrupt to check.
*
* @retval true If the interrupt is enabled.
* @retval false If the interrupt is not enabled.
*/
__STATIC_INLINE bool nrf_twi_int_enable_check(NRF_TWI_Type * p_twi,
nrf_twi_int_mask_t int_mask);
/**
* @brief Function for enabling the TWI peripheral.
*
* @param[in] p_twi TWI instance.
*/
__STATIC_INLINE void nrf_twi_enable(NRF_TWI_Type * p_twi);
/**
* @brief Function for disabling the TWI peripheral.
*
* @param[in] p_twi TWI instance.
*/
__STATIC_INLINE void nrf_twi_disable(NRF_TWI_Type * p_twi);
/**
* @brief Function for configuring TWI pins.
*
*
* @param[in] p_twi TWI instance.
* @param[in] scl_pin SCL pin number.
* @param[in] sda_pin SDA pin number.
*/
__STATIC_INLINE void nrf_twi_pins_set(NRF_TWI_Type * p_twi,
uint32_t scl_pin,
uint32_t sda_pin);
/**
* @brief Function for setting the TWI master clock frequency.
*
* @param[in] p_twi TWI instance.
* @param[in] frequency TWI frequency.
*/
__STATIC_INLINE void nrf_twi_frequency_set(NRF_TWI_Type * p_twi,
nrf_twi_frequency_t frequency);
/**
* @brief Function for checking the TWI error source.
*
* The error flags are cleared after reading.
*
* @param[in] p_twi TWI instance.
*
* @return Mask with error source flags.
*/
__STATIC_INLINE uint32_t nrf_twi_errorsrc_get_and_clear(NRF_TWI_Type * p_twi);
/**
* @brief Function for setting the address to be used in TWI transfers.
*
* @param[in] p_twi TWI instance.
* @param[in] address Address to be used in transfers.
*/
__STATIC_INLINE void nrf_twi_address_set(NRF_TWI_Type * p_twi, uint8_t address);
/**
* @brief Function for reading data received by TWI.
*
* @param[in] p_twi TWI instance.
*
* @return Received data.
*/
__STATIC_INLINE uint8_t nrf_twi_rxd_get(NRF_TWI_Type * p_twi);
/**
* @brief Function for writing data to be transmitted by TWI.
*
* @param[in] p_twi TWI instance.
* @param[in] data Data to be transmitted.
*/
__STATIC_INLINE void nrf_twi_txd_set(NRF_TWI_Type * p_twi, uint8_t data);
__STATIC_INLINE void nrf_twi_shorts_set(NRF_TWI_Type * p_twi,
uint32_t shorts_mask);
/**
* @}
*/
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE void nrf_twi_task_trigger(NRF_TWI_Type * p_twi,
nrf_twi_task_t task)
{
*((volatile uint32_t *)((uint8_t *)p_twi + (uint32_t)task)) = 0x1UL;
}
__STATIC_INLINE uint32_t * nrf_twi_task_address_get(NRF_TWI_Type * p_twi,
nrf_twi_task_t task)
{
return (uint32_t *)((uint8_t *)p_twi + (uint32_t)task);
}
__STATIC_INLINE void nrf_twi_event_clear(NRF_TWI_Type * p_twi,
nrf_twi_event_t event)
{
*((volatile uint32_t *)((uint8_t *)p_twi + (uint32_t)event)) = 0x0UL;
}
__STATIC_INLINE bool nrf_twi_event_check(NRF_TWI_Type * p_twi,
nrf_twi_event_t event)
{
return (bool)*(volatile uint32_t *)((uint8_t *)p_twi + (uint32_t)event);
}
__STATIC_INLINE uint32_t * nrf_twi_event_address_get(NRF_TWI_Type * p_twi,
nrf_twi_event_t event)
{
return (uint32_t *)((uint8_t *)p_twi + (uint32_t)event);
}
__STATIC_INLINE void nrf_twi_shorts_enable(NRF_TWI_Type * p_twi,
uint32_t shorts_mask)
{
p_twi->SHORTS |= shorts_mask;
}
__STATIC_INLINE void nrf_twi_shorts_disable(NRF_TWI_Type * p_twi,
uint32_t shorts_mask)
{
p_twi->SHORTS &= ~(shorts_mask);
}
__STATIC_INLINE void nrf_twi_int_enable(NRF_TWI_Type * p_twi,
uint32_t int_mask)
{
p_twi->INTENSET = int_mask;
}
__STATIC_INLINE void nrf_twi_int_disable(NRF_TWI_Type * p_twi,
uint32_t int_mask)
{
p_twi->INTENCLR = int_mask;
}
__STATIC_INLINE bool nrf_twi_int_enable_check(NRF_TWI_Type * p_twi,
nrf_twi_int_mask_t int_mask)
{
return (bool)(p_twi->INTENSET & int_mask);
}
__STATIC_INLINE void nrf_twi_enable(NRF_TWI_Type * p_twi)
{
p_twi->ENABLE = (TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos);
}
__STATIC_INLINE void nrf_twi_disable(NRF_TWI_Type * p_twi)
{
p_twi->ENABLE = (TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos);
}
__STATIC_INLINE void nrf_twi_pins_set(NRF_TWI_Type * p_twi,
uint32_t scl_pin,
uint32_t sda_pin)
{
p_twi->PSELSCL = scl_pin;
p_twi->PSELSDA = sda_pin;
}
__STATIC_INLINE void nrf_twi_frequency_set(NRF_TWI_Type * p_twi,
nrf_twi_frequency_t frequency)
{
p_twi->FREQUENCY = frequency;
}
__STATIC_INLINE uint32_t nrf_twi_errorsrc_get_and_clear(NRF_TWI_Type * p_twi)
{
uint32_t error_source = p_twi->ERRORSRC;
// [error flags are cleared by writing '1' on their position]
p_twi->ERRORSRC = error_source;
return error_source;
}
__STATIC_INLINE void nrf_twi_address_set(NRF_TWI_Type * p_twi, uint8_t address)
{
p_twi->ADDRESS = address;
}
__STATIC_INLINE uint8_t nrf_twi_rxd_get(NRF_TWI_Type * p_twi)
{
return (uint8_t)p_twi->RXD;
}
__STATIC_INLINE void nrf_twi_txd_set(NRF_TWI_Type * p_twi, uint8_t data)
{
p_twi->TXD = data;
}
__STATIC_INLINE void nrf_twi_shorts_set(NRF_TWI_Type * p_twi,
uint32_t shorts_mask)
{
p_twi->SHORTS = shorts_mask;
}
#endif // SUPPRESS_INLINE_IMPLEMENTATION
#endif // NRF_TWI_H__

View File

@ -1,498 +0,0 @@
/*
* Copyright (c) 2015 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 or object form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER 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_UART_H__
#define NRF_UART_H__
#include "nrf.h"
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
/**
* @defgroup nrf_uart_hal UART HAL
* @{
* @ingroup nrf_uart
*
* @brief Hardware access layer for accessing the UART peripheral.
*/
#define NRF_UART_PSEL_DISCONNECTED 0xFFFFFFFF
/**
* @enum nrf_uart_task_t
* @brief UART tasks.
*/
typedef enum
{
/*lint -save -e30 -esym(628,__INTADDR__)*/
NRF_UART_TASK_STARTRX = offsetof(NRF_UART_Type, TASKS_STARTRX), /**< Task for starting reception. */
NRF_UART_TASK_STOPRX = offsetof(NRF_UART_Type, TASKS_STOPRX), /**< Task for stopping reception. */
NRF_UART_TASK_STARTTX = offsetof(NRF_UART_Type, TASKS_STARTTX), /**< Task for starting transmission. */
NRF_UART_TASK_STOPTX = offsetof(NRF_UART_Type, TASKS_STOPTX), /**< Task for stopping transmission. */
NRF_UART_TASK_SUSPEND = offsetof(NRF_UART_Type, TASKS_SUSPEND), /**< Task for suspending UART. */
/*lint -restore*/
} nrf_uart_task_t;
/**
* @enum nrf_uart_event_t
* @brief UART events.
*/
typedef enum
{
/*lint -save -e30*/
NRF_UART_EVENT_CTS = offsetof(NRF_UART_Type, EVENTS_CTS), /**< Event from CTS line activation. */
NRF_UART_EVENT_NCTS = offsetof(NRF_UART_Type, EVENTS_NCTS), /**< Event from CTS line deactivation. */
NRF_UART_EVENT_RXDRDY = offsetof(NRF_UART_Type, EVENTS_RXDRDY),/**< Event from data ready in RXD. */
NRF_UART_EVENT_TXDRDY = offsetof(NRF_UART_Type, EVENTS_TXDRDY),/**< Event from data sent from TXD. */
NRF_UART_EVENT_ERROR = offsetof(NRF_UART_Type, EVENTS_ERROR), /**< Event from error detection. */
NRF_UART_EVENT_RXTO = offsetof(NRF_UART_Type, EVENTS_RXTO) /**< Event from receiver timeout. */
/*lint -restore*/
} nrf_uart_event_t;
/**
* @enum nrf_uart_int_mask_t
* @brief UART interrupts.
*/
typedef enum
{
/*lint -save -e30*/
NRF_UART_INT_MASK_CTS = UART_INTENCLR_CTS_Msk, /**< CTS line activation interrupt. */
NRF_UART_INT_MASK_NCTS = UART_INTENCLR_NCTS_Msk, /**< CTS line deactivation interrupt. */
NRF_UART_INT_MASK_RXDRDY = UART_INTENCLR_RXDRDY_Msk, /**< Data ready in RXD interrupt. */
NRF_UART_INT_MASK_TXDRDY = UART_INTENCLR_TXDRDY_Msk, /**< Data sent from TXD interrupt. */
NRF_UART_INT_MASK_ERROR = UART_INTENCLR_ERROR_Msk, /**< Error detection interrupt. */
NRF_UART_INT_MASK_RXTO = UART_INTENCLR_RXTO_Msk /**< Receiver timeout interrupt. */
/*lint -restore*/
} nrf_uart_int_mask_t;
/**
* @enum nrf_uart_baudrate_t
* @brief Baudrates supported by UART.
*/
typedef enum
{
#ifdef NRF52
NRF_UART_BAUDRATE_1200 = UARTE_BAUDRATE_BAUDRATE_Baud1200, /**< 1200 baud. */
NRF_UART_BAUDRATE_2400 = UARTE_BAUDRATE_BAUDRATE_Baud2400, /**< 2400 baud. */
NRF_UART_BAUDRATE_4800 = UARTE_BAUDRATE_BAUDRATE_Baud4800, /**< 4800 baud. */
NRF_UART_BAUDRATE_9600 = UARTE_BAUDRATE_BAUDRATE_Baud9600, /**< 9600 baud. */
NRF_UART_BAUDRATE_14400 = UARTE_BAUDRATE_BAUDRATE_Baud14400, /**< 14400 baud. */
NRF_UART_BAUDRATE_19200 = UARTE_BAUDRATE_BAUDRATE_Baud19200, /**< 19200 baud. */
NRF_UART_BAUDRATE_28800 = UARTE_BAUDRATE_BAUDRATE_Baud28800, /**< 28800 baud. */
NRF_UART_BAUDRATE_38400 = UARTE_BAUDRATE_BAUDRATE_Baud38400, /**< 38400 baud. */
NRF_UART_BAUDRATE_57600 = UARTE_BAUDRATE_BAUDRATE_Baud57600, /**< 57600 baud. */
NRF_UART_BAUDRATE_76800 = UARTE_BAUDRATE_BAUDRATE_Baud76800, /**< 76800 baud. */
NRF_UART_BAUDRATE_115200 = UARTE_BAUDRATE_BAUDRATE_Baud115200, /**< 115200 baud. */
NRF_UART_BAUDRATE_230400 = UARTE_BAUDRATE_BAUDRATE_Baud230400, /**< 230400 baud. */
NRF_UART_BAUDRATE_250000 = UARTE_BAUDRATE_BAUDRATE_Baud250000, /**< 250000 baud. */
NRF_UART_BAUDRATE_460800 = UARTE_BAUDRATE_BAUDRATE_Baud460800, /**< 460800 baud. */
NRF_UART_BAUDRATE_921600 = UARTE_BAUDRATE_BAUDRATE_Baud921600, /**< 921600 baud. */
NRF_UART_BAUDRATE_1000000 = UARTE_BAUDRATE_BAUDRATE_Baud1M, /**< 1000000 baud. */
#else
NRF_UART_BAUDRATE_1200 = UART_BAUDRATE_BAUDRATE_Baud1200, /**< 1200 baud. */
NRF_UART_BAUDRATE_2400 = UART_BAUDRATE_BAUDRATE_Baud2400, /**< 2400 baud. */
NRF_UART_BAUDRATE_4800 = UART_BAUDRATE_BAUDRATE_Baud4800, /**< 4800 baud. */
NRF_UART_BAUDRATE_9600 = UART_BAUDRATE_BAUDRATE_Baud9600, /**< 9600 baud. */
NRF_UART_BAUDRATE_14400 = UART_BAUDRATE_BAUDRATE_Baud14400, /**< 14400 baud. */
NRF_UART_BAUDRATE_19200 = UART_BAUDRATE_BAUDRATE_Baud19200, /**< 19200 baud. */
NRF_UART_BAUDRATE_28800 = UART_BAUDRATE_BAUDRATE_Baud28800, /**< 28800 baud. */
NRF_UART_BAUDRATE_38400 = UART_BAUDRATE_BAUDRATE_Baud38400, /**< 38400 baud. */
NRF_UART_BAUDRATE_57600 = UART_BAUDRATE_BAUDRATE_Baud57600, /**< 57600 baud. */
NRF_UART_BAUDRATE_76800 = UART_BAUDRATE_BAUDRATE_Baud76800, /**< 76800 baud. */
NRF_UART_BAUDRATE_115200 = UART_BAUDRATE_BAUDRATE_Baud115200, /**< 115200 baud. */
NRF_UART_BAUDRATE_230400 = UART_BAUDRATE_BAUDRATE_Baud230400, /**< 230400 baud. */
NRF_UART_BAUDRATE_250000 = UART_BAUDRATE_BAUDRATE_Baud250000, /**< 250000 baud. */
NRF_UART_BAUDRATE_460800 = UART_BAUDRATE_BAUDRATE_Baud460800, /**< 460800 baud. */
NRF_UART_BAUDRATE_921600 = UART_BAUDRATE_BAUDRATE_Baud921600, /**< 921600 baud. */
NRF_UART_BAUDRATE_1000000 = UART_BAUDRATE_BAUDRATE_Baud1M, /**< 1000000 baud. */
#endif
} nrf_uart_baudrate_t;
/**
* @enum nrf_uart_error_mask_t
* @brief Types of UART error masks.
*/
typedef enum
{
NRF_UART_ERROR_OVERRUN_MASK = UART_ERRORSRC_OVERRUN_Msk, /**< Overrun error. */
NRF_UART_ERROR_PARITY_MASK = UART_ERRORSRC_PARITY_Msk, /**< Parity error. */
NRF_UART_ERROR_FRAMING_MASK = UART_ERRORSRC_FRAMING_Msk, /**< Framing error. */
NRF_UART_ERROR_BREAK_MASK = UART_ERRORSRC_BREAK_Msk, /**< Break error. */
} nrf_uart_error_mask_t;
/**
* @enum nrf_uart_parity_t
* @brief Types of UART parity modes.
*/
typedef enum
{
NRF_UART_PARITY_EXCLUDED = UART_CONFIG_PARITY_Excluded << UART_CONFIG_PARITY_Pos, /**< Parity excluded. */
NRF_UART_PARITY_INCLUDED = UART_CONFIG_PARITY_Included << UART_CONFIG_PARITY_Pos, /**< Parity included. */
} nrf_uart_parity_t;
/**
* @enum nrf_uart_hwfc_t
* @brief Types of UART flow control modes.
*/
typedef enum
{
NRF_UART_HWFC_DISABLED = UART_CONFIG_HWFC_Disabled, /**< HW flow control disabled. */
NRF_UART_HWFC_ENABLED = UART_CONFIG_HWFC_Enabled, /**< HW flow control enabled. */
} nrf_uart_hwfc_t;
/**
* @brief Function for clearing a specific UART event.
*
* @param[in] p_reg UART instance.
* @param[in] event Event to clear.
*/
__STATIC_INLINE void nrf_uart_event_clear(NRF_UART_Type * p_reg, nrf_uart_event_t event);
/**
* @brief Function for checking the state of a specific UART event.
*
* @param[in] p_reg UART instance.
* @param[in] event Event to check.
*
* @retval True if event is set, False otherwise.
*/
__STATIC_INLINE bool nrf_uart_event_check(NRF_UART_Type * p_reg, nrf_uart_event_t event);
/**
* @brief Function for returning the address of a specific UART event register.
*
* @param[in] p_reg UART instance.
* @param[in] event Desired event.
*
* @retval Address of specified event register.
*/
__STATIC_INLINE uint32_t nrf_uart_event_address_get(NRF_UART_Type * p_reg,
nrf_uart_event_t event);
/**
* @brief Function for enabling a specific interrupt.
*
* @param p_reg Instance.
* @param int_mask Interrupts to enable.
*/
__STATIC_INLINE void nrf_uart_int_enable(NRF_UART_Type * p_reg, uint32_t int_mask);
/**
* @brief Function for retrieving the state of a given interrupt.
*
* @param p_reg Instance.
* @param int_mask Mask of interrupt to check.
*
* @retval true If the interrupt is enabled.
* @retval false If the interrupt is not enabled.
*/
__STATIC_INLINE bool nrf_uart_int_enable_check(NRF_UART_Type * p_reg, uint32_t int_mask);
/**
* @brief Function for disabling specific interrupts.
*
* @param p_reg Instance.
* @param int_mask Interrupts to disable.
*/
__STATIC_INLINE void nrf_uart_int_disable(NRF_UART_Type * p_reg, uint32_t int_mask);
/**
* @brief Function for getting error source mask. Function is clearing error source flags after reading.
*
* @param p_reg Instance.
* @return Mask with error source flags.
*/
__STATIC_INLINE uint32_t nrf_uart_errorsrc_get_and_clear(NRF_UART_Type * p_reg);
/**
* @brief Function for enabling UART.
*
* @param p_reg Instance.
*/
__STATIC_INLINE void nrf_uart_enable(NRF_UART_Type * p_reg);
/**
* @brief Function for disabling UART.
*
* @param p_reg Instance.
*/
__STATIC_INLINE void nrf_uart_disable(NRF_UART_Type * p_reg);
/**
* @brief Function for configuring TX/RX pins.
*
* @param p_reg Instance.
* @param pseltxd TXD pin number.
* @param pselrxd RXD pin number.
*/
__STATIC_INLINE void nrf_uart_txrx_pins_set(NRF_UART_Type * p_reg, uint32_t pseltxd, uint32_t pselrxd);
/**
* @brief Function for disconnecting TX/RX pins.
*
* @param p_reg Instance.
*/
__STATIC_INLINE void nrf_uart_txrx_pins_disconnect(NRF_UART_Type * p_reg);
/**
* @brief Function for getting TX pin.
*
* @param p_reg Instance.
*/
__STATIC_INLINE uint32_t nrf_uart_tx_pin_get(NRF_UART_Type * p_reg);
/**
* @brief Function for getting RX pin.
*
* @param p_reg Instance.
*/
__STATIC_INLINE uint32_t nrf_uart_rx_pin_get(NRF_UART_Type * p_reg);
/**
* @brief Function for getting RTS pin.
*
* @param p_reg Instance.
*/
__STATIC_INLINE uint32_t nrf_uart_rts_pin_get(NRF_UART_Type * p_reg);
/**
* @brief Function for getting CTS pin.
*
* @param p_reg Instance.
*/
__STATIC_INLINE uint32_t nrf_uart_cts_pin_get(NRF_UART_Type * p_reg);
/**
* @brief Function for configuring flow control pins.
*
* @param p_reg Instance.
* @param pselrts RTS pin number.
* @param pselcts CTS pin number.
*/
__STATIC_INLINE void nrf_uart_hwfc_pins_set(NRF_UART_Type * p_reg,
uint32_t pselrts,
uint32_t pselcts);
/**
* @brief Function for disconnecting flow control pins.
*
* @param p_reg Instance.
*/
__STATIC_INLINE void nrf_uart_hwfc_pins_disconnect(NRF_UART_Type * p_reg);
/**
* @brief Function for reading RX data.
*
* @param p_reg Instance.
* @return Received byte.
*/
__STATIC_INLINE uint8_t nrf_uart_rxd_get(NRF_UART_Type * p_reg);
/**
* @brief Function for setting Tx data.
*
* @param p_reg Instance.
* @param txd Byte.
*/
__STATIC_INLINE void nrf_uart_txd_set(NRF_UART_Type * p_reg, uint8_t txd);
/**
* @brief Function for starting an UART task.
*
* @param p_reg Instance.
* @param task Task.
*/
__STATIC_INLINE void nrf_uart_task_trigger(NRF_UART_Type * p_reg, nrf_uart_task_t task);
/**
* @brief Function for returning the address of a specific task register.
*
* @param p_reg Instance.
* @param task Task.
*
* @return Task address.
*/
__STATIC_INLINE uint32_t nrf_uart_task_address_get(NRF_UART_Type * p_reg, nrf_uart_task_t task);
/**
* @brief Function for configuring UART.
*
* @param p_reg Instance.
* @param hwfc Hardware flow control. Enabled if true.
* @param parity Parity. Included if true.
*/
__STATIC_INLINE void nrf_uart_configure(NRF_UART_Type * p_reg,
nrf_uart_parity_t parity,
nrf_uart_hwfc_t hwfc);
/**
* @brief Function for setting UART baudrate.
*
* @param p_reg Instance.
* @param baudrate Baudrate.
*/
__STATIC_INLINE void nrf_uart_baudrate_set(NRF_UART_Type * p_reg, nrf_uart_baudrate_t baudrate);
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
__STATIC_INLINE void nrf_uart_event_clear(NRF_UART_Type * p_reg, nrf_uart_event_t event)
{
*((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event)) = 0x0UL;
}
__STATIC_INLINE bool nrf_uart_event_check(NRF_UART_Type * p_reg, nrf_uart_event_t event)
{
return (bool)*(volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)event);
}
__STATIC_INLINE uint32_t nrf_uart_event_address_get(NRF_UART_Type * p_reg,
nrf_uart_event_t event)
{
return (uint32_t)((uint8_t *)p_reg + (uint32_t)event);
}
__STATIC_INLINE void nrf_uart_int_enable(NRF_UART_Type * p_reg, uint32_t int_mask)
{
p_reg->INTENSET = int_mask;
}
__STATIC_INLINE bool nrf_uart_int_enable_check(NRF_UART_Type * p_reg, uint32_t int_mask)
{
return (bool)(p_reg->INTENSET & int_mask);
}
__STATIC_INLINE void nrf_uart_int_disable(NRF_UART_Type * p_reg, uint32_t int_mask)
{
p_reg->INTENCLR = int_mask;
}
__STATIC_INLINE uint32_t nrf_uart_errorsrc_get_and_clear(NRF_UART_Type * p_reg)
{
uint32_t errsrc_mask = p_reg->ERRORSRC;
p_reg->ERRORSRC = errsrc_mask;
return errsrc_mask;
}
__STATIC_INLINE void nrf_uart_enable(NRF_UART_Type * p_reg)
{
p_reg->ENABLE = UART_ENABLE_ENABLE_Enabled;
}
__STATIC_INLINE void nrf_uart_disable(NRF_UART_Type * p_reg)
{
p_reg->ENABLE = UART_ENABLE_ENABLE_Disabled;
}
__STATIC_INLINE void nrf_uart_txrx_pins_set(NRF_UART_Type * p_reg, uint32_t pseltxd, uint32_t pselrxd)
{
p_reg->PSELTXD = pseltxd;
p_reg->PSELRXD = pselrxd;
}
__STATIC_INLINE void nrf_uart_txrx_pins_disconnect(NRF_UART_Type * p_reg)
{
nrf_uart_txrx_pins_set(p_reg, NRF_UART_PSEL_DISCONNECTED, NRF_UART_PSEL_DISCONNECTED);
}
__STATIC_INLINE uint32_t nrf_uart_tx_pin_get(NRF_UART_Type * p_reg)
{
return p_reg->PSELTXD;
}
__STATIC_INLINE uint32_t nrf_uart_rx_pin_get(NRF_UART_Type * p_reg)
{
return p_reg->PSELRXD;
}
__STATIC_INLINE uint32_t nrf_uart_rts_pin_get(NRF_UART_Type * p_reg)
{
return p_reg->PSELRTS;
}
__STATIC_INLINE uint32_t nrf_uart_cts_pin_get(NRF_UART_Type * p_reg)
{
return p_reg->PSELCTS;
}
__STATIC_INLINE void nrf_uart_hwfc_pins_set(NRF_UART_Type * p_reg, uint32_t pselrts, uint32_t pselcts)
{
p_reg->PSELRTS = pselrts;
p_reg->PSELCTS = pselcts;
}
__STATIC_INLINE void nrf_uart_hwfc_pins_disconnect(NRF_UART_Type * p_reg)
{
nrf_uart_hwfc_pins_set(p_reg, NRF_UART_PSEL_DISCONNECTED, NRF_UART_PSEL_DISCONNECTED);
}
__STATIC_INLINE uint8_t nrf_uart_rxd_get(NRF_UART_Type * p_reg)
{
return p_reg->RXD;
}
__STATIC_INLINE void nrf_uart_txd_set(NRF_UART_Type * p_reg, uint8_t txd)
{
p_reg->TXD = txd;
}
__STATIC_INLINE void nrf_uart_task_trigger(NRF_UART_Type * p_reg, nrf_uart_task_t task)
{
*((volatile uint32_t *)((uint8_t *)p_reg + (uint32_t)task)) = 0x1UL;
}
__STATIC_INLINE uint32_t nrf_uart_task_address_get(NRF_UART_Type * p_reg, nrf_uart_task_t task)
{
return (uint32_t)p_reg + (uint32_t)task;
}
__STATIC_INLINE void nrf_uart_configure(NRF_UART_Type * p_reg,
nrf_uart_parity_t parity,
nrf_uart_hwfc_t hwfc)
{
p_reg->CONFIG = (uint32_t)parity | (uint32_t)hwfc;
}
__STATIC_INLINE void nrf_uart_baudrate_set(NRF_UART_Type * p_reg, nrf_uart_baudrate_t baudrate)
{
p_reg->BAUDRATE = baudrate;
}
#endif //SUPPRESS_INLINE_IMPLEMENTATION
/** @} */
#endif //NRF_UART_H__

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