初始版本

This commit is contained in:
xiaozhengsheng
2025-08-19 09:49:41 +08:00
parent 10f1ddf1c1
commit 6df0f7d96e
2974 changed files with 1712873 additions and 54 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,649 @@
/**
* Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __NRF_ESB_H
#define __NRF_ESB_H
#include <stdbool.h>
#include <stdint.h>
#include "nrf.h"
#include "app_util.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @defgroup nrf_esb Enhanced ShockBurst
* @{
* @ingroup proprietary_api
*
* @brief Enhanced ShockBurst (ESB) is a basic protocol that supports two-way data
* packet communication including packet buffering, packet acknowledgment,
* and automatic retransmission of lost packets.
*/
/** @name Debug pins
* @{
* @brief If NRF_ESB_DEBUG is defined, these GPIO pins can be used for debug timing.
*/
#ifndef NRF52840_XXAA
#define DEBUGPIN1 12 //!< If NRF_ESB_DEBUG is defined, this GPIO pin is set with every radio interrupt.
#define DEBUGPIN2 13 //!< If NRF_ESB_DEBUG is defined, this GPIO pin is set with every NRF_RADIO->EVENTS_END.
#define DEBUGPIN3 14 //!< If NRF_ESB_DEBUG is defined, this GPIO pin is set with every NRF_RADIO->EVENTS_DISABLED.
#define DEBUGPIN4 15 //!< If NRF_ESB_DEBUG is defined, this GPIO pin is set when the radio is set to start transmission.
#else
#define DEBUGPIN1 24 //!< If NRF_ESB_DEBUG is defined, this GPIO pin is set with every radio interrupt.
#define DEBUGPIN2 25 //!< If NRF_ESB_DEBUG is defined, this GPIO pin is set with every NRF_RADIO->EVENTS_END.
#define DEBUGPIN3 26 //!< If NRF_ESB_DEBUG is defined, this GPIO pin is set with every NRF_RADIO->EVENTS_DISABLED.
#define DEBUGPIN4 27 //!< If NRF_ESB_DEBUG is defined, this GPIO pin is set when the radio is set to start transmission.
#endif
#ifdef NRF_ESB_DEBUG
#define DEBUG_PIN_SET(a) (NRF_GPIO->OUTSET = (1 << (a))) //!< Used internally to set debug pins.
#define DEBUG_PIN_CLR(a) (NRF_GPIO->OUTCLR = (1 << (a))) //!< Used internally to clear debug pins.
#else
#define DEBUG_PIN_SET(a) //!< Used internally to set debug pins.
#define DEBUG_PIN_CLR(a) //!< Used internally to clear debug pins.
#endif
/** @} */
// Hardcoded parameters - change if necessary
#ifndef NRF_ESB_MAX_PAYLOAD_LENGTH
#define NRF_ESB_MAX_PAYLOAD_LENGTH 32 //!< The maximum size of the payload. Valid values are 1 to 252.
#endif
#define NRF_ESB_TX_FIFO_SIZE 8 //!< The size of the transmission first-in, first-out buffer.
#define NRF_ESB_RX_FIFO_SIZE 8 //!< The size of the reception first-in, first-out buffer.
// 252 is the largest possible payload size according to the nRF5 architecture.
STATIC_ASSERT(NRF_ESB_MAX_PAYLOAD_LENGTH <= 252);
#define NRF_ESB_SYS_TIMER NRF_TIMER2 //!< The timer that is used by the module.
#define NRF_ESB_SYS_TIMER_IRQ_Handler TIMER2_IRQHandler //!< The handler that is used by @ref NRF_ESB_SYS_TIMER.
#define NRF_ESB_PPI_TIMER_START 10 //!< The PPI channel used for starting the timer.
#define NRF_ESB_PPI_TIMER_STOP 11 //!< The PPI channel used for stopping the timer.
#define NRF_ESB_PPI_RX_TIMEOUT 12 //!< The PPI channel used for RX time-out.
#define NRF_ESB_PPI_TX_START 13 //!< The PPI channel used for starting TX.
#ifndef NRF_ESB_PIPE_COUNT
#define NRF_ESB_PIPE_COUNT 8 //!< The maximum number of pipes allowed in the API, can be used if you need to restrict the number of pipes used. Must be 8 or lower because of architectural limitations.
#endif
STATIC_ASSERT(NRF_ESB_PIPE_COUNT <= 8);
/**@cond NO_DOXYGEN */
#ifdef NRF52832_XXAA
// nRF52 address fix timer and PPI defines
#define NRF_ESB_PPI_BUGFIX1 9
#define NRF_ESB_PPI_BUGFIX2 8
#define NRF_ESB_PPI_BUGFIX3 7
#define NRF_ESB_BUGFIX_TIMER NRF_TIMER3
#define NRF_ESB_BUGFIX_TIMER_IRQn TIMER3_IRQn
#define NRF_ESB_BUGFIX_TIMER_IRQHandler TIMER3_IRQHandler
#endif
/** @endcond */
// Interrupt flags
#define NRF_ESB_INT_TX_SUCCESS_MSK 0x01 //!< The flag used to indicate a success since the last event.
#define NRF_ESB_INT_TX_FAILED_MSK 0x02 //!< The flag used to indicate a failure since the last event.
#define NRF_ESB_INT_RX_DR_MSK 0x04 //!< The flag used to indicate that a packet was received since the last event.
#define NRF_ESB_PID_RESET_VALUE 0xFF //!< Invalid PID value that is guaranteed to not collide with any valid PID value.
#define NRF_ESB_PID_MAX 3 //!< The maximum value for PID.
#define NRF_ESB_CRC_RESET_VALUE 0xFFFF //!< The CRC reset value.
#define ESB_EVT_IRQ SWI0_IRQn //!< The ESB event IRQ number when running on an nRF5 device.
#define ESB_EVT_IRQHandler SWI0_IRQHandler //!< The handler for @ref ESB_EVT_IRQ when running on an nRF5 device.
#if defined(NRF52_SERIES)
#define ESB_IRQ_PRIORITY_MSK 0x07 //!< The mask used to enforce a valid IRQ priority.
#else
#define ESB_IRQ_PRIORITY_MSK 0x03 //!< The mask used to enforce a valid IRQ priority.
#endif
/** @brief Default address configuration for ESB.
* @details Roughly equal to the nRF24Lxx default (except for the number of pipes, because more pipes are supported). */
#define NRF_ESB_ADDR_DEFAULT \
{ \
.base_addr_p0 = { 0xE7, 0xE7, 0xE7, 0xE7 }, \
.base_addr_p1 = { 0xC2, 0xC2, 0xC2, 0xC2 }, \
.pipe_prefixes = { 0xE7, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8 }, \
.addr_length = 5, \
.num_pipes = NRF_ESB_PIPE_COUNT, \
.rf_channel = 2, \
.rx_pipes_enabled = 0xFF \
}
/** @brief Default radio parameters.
* @details Roughly equal to the nRF24Lxx default parameters (except for CRC, which is set to 16 bit, and protocol, which is set to DPL). */
#define NRF_ESB_DEFAULT_CONFIG {.protocol = NRF_ESB_PROTOCOL_ESB_DPL, \
.mode = NRF_ESB_MODE_PTX, \
.event_handler = 0, \
.bitrate = NRF_ESB_BITRATE_2MBPS, \
.crc = NRF_ESB_CRC_16BIT, \
.tx_output_power = NRF_ESB_TX_POWER_0DBM, \
.retransmit_delay = 250, \
.retransmit_count = 3, \
.tx_mode = NRF_ESB_TXMODE_AUTO, \
.radio_irq_priority = 1, \
.event_irq_priority = 2, \
.payload_length = 32, \
.selective_auto_ack = false \
}
/** @brief Default legacy radio parameters. Identical to the nRF24Lxx defaults. */
#define NRF_ESB_LEGACY_CONFIG {.protocol = NRF_ESB_PROTOCOL_ESB, \
.mode = NRF_ESB_MODE_PTX, \
.event_handler = 0, \
.bitrate = NRF_ESB_BITRATE_2MBPS, \
.crc = NRF_ESB_CRC_8BIT, \
.tx_output_power = NRF_ESB_TX_POWER_0DBM, \
.retransmit_delay = 600, \
.retransmit_count = 3, \
.tx_mode = NRF_ESB_TXMODE_AUTO, \
.radio_irq_priority = 1, \
.event_irq_priority = 2, \
.payload_length = 32, \
.selective_auto_ack = false \
}
/** @brief Macro to create an initializer for a TX data packet.
*
* @details This macro generates an initializer. Using the initializer is more efficient
* than setting the individual parameters dynamically.
*
* @param[in] _pipe The pipe to use for the data packet.
* @param[in] ... Comma separated list of character data to put in the TX buffer.
* Supported values consist of 1 to 63 characters.
*
* @return Initializer that sets up the pipe, length, and byte array for content of the TX data.
*/
#define NRF_ESB_CREATE_PAYLOAD(_pipe, ...) \
{.pipe = _pipe, .length = NUM_VA_ARGS(__VA_ARGS__), .data = {__VA_ARGS__}}; \
STATIC_ASSERT(NUM_VA_ARGS(__VA_ARGS__) > 0 && NUM_VA_ARGS(__VA_ARGS__) <= 63)
/**@brief Enhanced ShockBurst protocols. */
typedef enum {
NRF_ESB_PROTOCOL_ESB, /**< Enhanced ShockBurst with fixed payload length. */
NRF_ESB_PROTOCOL_ESB_DPL /**< Enhanced ShockBurst with dynamic payload length. */
} nrf_esb_protocol_t;
/**@brief Enhanced ShockBurst modes. */
typedef enum {
NRF_ESB_MODE_PTX, /**< Primary transmitter mode. */
NRF_ESB_MODE_PRX /**< Primary receiver mode. */
} nrf_esb_mode_t;
/**@brief Enhanced ShockBurst bitrate modes. */
typedef enum {
NRF_ESB_BITRATE_2MBPS = RADIO_MODE_MODE_Nrf_2Mbit, /**< 2 Mb radio mode. */
NRF_ESB_BITRATE_1MBPS = RADIO_MODE_MODE_Nrf_1Mbit, /**< 1 Mb radio mode. */
#if defined(RADIO_MODE_MODE_Nrf_250Kbit)
NRF_ESB_BITRATE_250KBPS = RADIO_MODE_MODE_Nrf_250Kbit, /**< 250 Kb radio mode. */
#endif //!( defined(NRF52840_XXAA) || defined(NRF52810_XXAA) || defined(NRF52811_XXAA) )
NRF_ESB_BITRATE_1MBPS_BLE = RADIO_MODE_MODE_Ble_1Mbit, /**< 1 Mb radio mode using @e Bluetooth low energy radio parameters. */
#if defined(RADIO_MODE_MODE_Ble_2Mbit)
NRF_ESB_BITRATE_2MBPS_BLE = RADIO_MODE_MODE_Ble_2Mbit /**< 2 Mb radio mode using @e Bluetooth low energy radio parameters. */
#endif
} nrf_esb_bitrate_t;
/**@brief Enhanced ShockBurst CRC modes. */
typedef enum {
NRF_ESB_CRC_16BIT = RADIO_CRCCNF_LEN_Two, /**< Use two-byte CRC. */
NRF_ESB_CRC_8BIT = RADIO_CRCCNF_LEN_One, /**< Use one-byte CRC. */
NRF_ESB_CRC_OFF = RADIO_CRCCNF_LEN_Disabled /**< Disable CRC. */
} nrf_esb_crc_t;
/**@brief Enhanced ShockBurst radio transmission power modes. */
typedef enum {
#if defined(RADIO_TXPOWER_TXPOWER_Pos8dBm)
NRF_ESB_TX_POWER_8DBM = RADIO_TXPOWER_TXPOWER_Pos8dBm, /**< 8 dBm radio transmit power. */
#endif
#if defined(RADIO_TXPOWER_TXPOWER_Pos7dBm)
NRF_ESB_TX_POWER_7DBM = RADIO_TXPOWER_TXPOWER_Pos7dBm, /**< 7 dBm radio transmit power. */
#endif
#if defined(RADIO_TXPOWER_TXPOWER_Pos6dBm)
NRF_ESB_TX_POWER_6DBM = RADIO_TXPOWER_TXPOWER_Pos6dBm, /**< 6 dBm radio transmit power. */
#endif
#if defined(RADIO_TXPOWER_TXPOWER_Pos5dBm)
NRF_ESB_TX_POWER_5DBM = RADIO_TXPOWER_TXPOWER_Pos5dBm, /**< 5 dBm radio transmit power. */
#endif
NRF_ESB_TX_POWER_4DBM = RADIO_TXPOWER_TXPOWER_Pos4dBm, /**< 4 dBm radio transmit power. */
#if defined(RADIO_TXPOWER_TXPOWER_Pos3dBm)
NRF_ESB_TX_POWER_3DBM = RADIO_TXPOWER_TXPOWER_Pos3dBm, /**< 3 dBm radio transmit power. */
#endif
#if defined(RADIO_TXPOWER_TXPOWER_Pos2dBm)
NRF_ESB_TX_POWER_2DBM = RADIO_TXPOWER_TXPOWER_Pos2dBm, /**< 2 dBm radio transmit power. */
#endif
NRF_ESB_TX_POWER_0DBM = RADIO_TXPOWER_TXPOWER_0dBm, /**< 0 dBm radio transmit power. */
NRF_ESB_TX_POWER_NEG4DBM = RADIO_TXPOWER_TXPOWER_Neg4dBm, /**< -4 dBm radio transmit power. */
NRF_ESB_TX_POWER_NEG8DBM = RADIO_TXPOWER_TXPOWER_Neg8dBm, /**< -8 dBm radio transmit power. */
NRF_ESB_TX_POWER_NEG12DBM = RADIO_TXPOWER_TXPOWER_Neg12dBm, /**< -12 dBm radio transmit power. */
NRF_ESB_TX_POWER_NEG16DBM = RADIO_TXPOWER_TXPOWER_Neg16dBm, /**< -16 dBm radio transmit power. */
NRF_ESB_TX_POWER_NEG20DBM = RADIO_TXPOWER_TXPOWER_Neg20dBm, /**< -20 dBm radio transmit power. */
NRF_ESB_TX_POWER_NEG30DBM = RADIO_TXPOWER_TXPOWER_Neg30dBm, /**< -30 dBm radio transmit power. */
NRF_ESB_TX_POWER_NEG40DBM = RADIO_TXPOWER_TXPOWER_Neg40dBm /**< -40 dBm radio transmit power. */
} nrf_esb_tx_power_t;
/**@brief Enhanced ShockBurst transmission modes. */
typedef enum {
NRF_ESB_TXMODE_AUTO, /**< Automatic TX mode: When the TX FIFO contains packets and the radio is idle, packets are sent automatically. */
NRF_ESB_TXMODE_MANUAL, /**< Manual TX mode: Packets are not sent until @ref nrf_esb_start_tx is called. This mode can be used to ensure consistent packet timing. */
NRF_ESB_TXMODE_MANUAL_START /**< Manual start TX mode: Packets are not sent until @ref nrf_esb_start_tx is called. Then, transmission continues automatically until the TX FIFO is empty. */
} nrf_esb_tx_mode_t;
/**@brief Enhanced ShockBurst event IDs used to indicate the type of the event. */
typedef enum
{
NRF_ESB_EVENT_TX_SUCCESS, /**< Event triggered on TX success. */
NRF_ESB_EVENT_TX_FAILED, /**< Event triggered on TX failure. */
NRF_ESB_EVENT_RX_RECEIVED /**< Event triggered on RX received. */
} nrf_esb_evt_id_t;
/**@brief Enhanced ShockBurst payload.
*
* @details The payload is used both for transmissions and for acknowledging a
* received packet with a payload.
*/
typedef struct
{
uint8_t length; //!< Length of the packet (maximum value is @ref NRF_ESB_MAX_PAYLOAD_LENGTH).
uint8_t pipe; //!< Pipe used for this payload.
int8_t rssi; //!< RSSI for the received packet.
uint8_t noack; //!< Flag indicating that this packet will not be acknowledgement. Flag is ignored when selective auto ack is enabled.
uint8_t pid; //!< PID assigned during communication.
uint8_t data[NRF_ESB_MAX_PAYLOAD_LENGTH]; //!< The payload data.
} nrf_esb_payload_t;
/**@brief Enhanced ShockBurst event. */
typedef struct
{
nrf_esb_evt_id_t evt_id; //!< Enhanced ShockBurst event ID.
uint32_t tx_attempts; //!< Number of TX retransmission attempts.
} nrf_esb_evt_t;
/**@brief Definition of the event handler for the module. */
typedef void (* nrf_esb_event_handler_t)(nrf_esb_evt_t const * p_event);
/**@brief Main configuration structure for the module. */
typedef struct
{
nrf_esb_protocol_t protocol; //!< Enhanced ShockBurst protocol.
nrf_esb_mode_t mode; //!< Enhanced ShockBurst mode.
nrf_esb_event_handler_t event_handler; //!< Enhanced ShockBurst event handler.
// General RF parameters
nrf_esb_bitrate_t bitrate; //!< Enhanced ShockBurst bitrate mode.
nrf_esb_crc_t crc; //!< Enhanced ShockBurst CRC mode.
nrf_esb_tx_power_t tx_output_power; //!< Enhanced ShockBurst radio transmission power mode.
uint16_t retransmit_delay; //!< The delay between each retransmission of unacknowledged packets.
uint16_t retransmit_count; //!< The number of retransmission attempts before transmission fail.
// Control settings
nrf_esb_tx_mode_t tx_mode; //!< Enhanced ShockBurst transmission mode.
uint8_t radio_irq_priority; //!< nRF radio interrupt priority.
uint8_t event_irq_priority; //!< ESB event interrupt priority.
uint8_t payload_length; //!< Length of the payload (maximum length depends on the platforms that are used on each side).
bool selective_auto_ack; //!< Enable or disable selective auto acknowledgement. When this feature is disabled, all packets will be acknowledged ignoring the noack field.
} nrf_esb_config_t;
/**@brief Function for initializing the Enhanced ShockBurst module.
*
* @param p_config Parameters for initializing the module.
*
* @retval NRF_SUCCESS If initialization was successful.
* @retval NRF_ERROR_NULL If the @p p_config argument was NULL.
* @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
*/
uint32_t nrf_esb_init(nrf_esb_config_t const * p_config);
/**@brief Function for suspending the Enhanced ShockBurst module.
*
* Calling this function stops ongoing communications without changing the queues.
*
* @retval NRF_SUCCESS If Enhanced ShockBurst was suspended.
* @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
*/
uint32_t nrf_esb_suspend(void);
/**@brief Function for disabling the Enhanced ShockBurst module.
*
* Calling this function disables the Enhanced ShockBurst module immediately.
* Doing so might stop ongoing communications.
*
* @note All queues are flushed by this function.
*
* @retval NRF_SUCCESS If Enhanced ShockBurst was disabled.
*/
uint32_t nrf_esb_disable(void);
/**@brief Function for checking if the Enhanced ShockBurst module is idle.
*
* @retval true If the module is idle.
* @retval false If the module is busy.
*/
bool nrf_esb_is_idle(void);
/**@brief Function for writing a payload for transmission or acknowledgement.
*
* This function writes a payload that is added to the queue. When the module is in PTX mode, the
* payload is queued for a regular transmission. When the module is in PRX mode, the payload
* is queued for when a packet is received that requires an acknowledgement with payload.
*
* @param[in] p_payload Pointer to the structure that contains information and state of the payload.
*
* @retval NRF_SUCCESS If the payload was successfully queued for writing.
* @retval NRF_ERROR_NULL If the required parameter was NULL.
* @retval NRF_INVALID_STATE If the module is not initialized.
* @retval NRF_ERROR_NO_MEM If the TX FIFO is full.
* @retval NRF_ERROR_INVALID_LENGTH If the payload length was invalid (zero or larger than the allowed maximum).
*/
uint32_t nrf_esb_write_payload(nrf_esb_payload_t const * p_payload);
/**@brief Function for reading an RX payload.
*
* @param[in,out] p_payload Pointer to the structure that contains information and state of the payload.
*
* @retval NRF_SUCCESS If the data was read successfully.
* @retval NRF_ERROR_NULL If the required parameter was NULL.
* @retval NRF_INVALID_STATE If the module is not initialized.
*/
uint32_t nrf_esb_read_rx_payload(nrf_esb_payload_t * p_payload);
/**@brief Function for starting transmission.
*
* @retval NRF_SUCCESS If the TX started successfully.
* @retval NRF_ERROR_BUFFER_EMPTY If the TX did not start because the FIFO buffer is empty.
* @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
*/
uint32_t nrf_esb_start_tx(void);
/**@brief Function for starting to transmit data from the FIFO buffer.
*
* @retval NRF_SUCCESS If the transmission was started successfully.
* @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
*/
uint32_t nrf_esb_start_rx(void);
/** @brief Function for stopping data reception.
*
* @retval NRF_SUCCESS If data reception was stopped successfully.
* @retval NRF_ESB_ERROR_NOT_IN_RX_MODE If the function failed because the module is not in RX mode.
*/
uint32_t nrf_esb_stop_rx(void);
/**@brief Function for removing remaining items from the TX buffer.
*
* This function clears the TX FIFO buffer.
*
* @retval NRF_SUCCESS If pending items in the TX buffer were successfully cleared.
* @retval NRF_INVALID_STATE If the module is not initialized.
*/
uint32_t nrf_esb_flush_tx(void);
/**@brief Function for removing the newest entry from the TX buffer.
*
* This function will remove the most recently added element from the FIFO queue.
*
* @retval NRF_SUCCESS If the operation completed successfully.
* @retval NRF_INVALID_STATE If the module is not initialized.
* @retval NRF_ERROR_BUFFER_EMPTY If there are no items in the queue to remove.
*/
uint32_t nrf_esb_pop_tx(void);
/**@brief Function for removing the oldest entry from the TX buffer.
*
* This function will remove the next element scheduled to be sent from the TX FIFO queue.
* This is useful if you want to skip a packet which was never acknowledged.
*
* @retval NRF_SUCCESS If the operation completed successfully.
* @retval NRF_INVALID_STATE If the module is not initialized.
* @retval NRF_ERROR_BUFFER_EMPTY If there are no items in the queue to remove.
*/
uint32_t nrf_esb_skip_tx(void);
/**@brief Function for removing remaining items from the RX buffer.
*
* @retval NRF_SUCCESS If the pending items in the RX buffer were successfully cleared.
* @retval NRF_INVALID_STATE If the module is not initialized.
*/
uint32_t nrf_esb_flush_rx(void);
/**@brief Function for setting the length of the address.
*
* @param[in] length Length of the ESB address (in bytes).
*
* @retval NRF_SUCCESS If the address length was set successfully.
* @retval NRF_ERROR_INVALID_PARAM If the address length was invalid.
* @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
*/
uint32_t nrf_esb_set_address_length(uint8_t length);
/**@brief Function for setting the base address for pipe 0.
*
* @param[in] p_addr Pointer to the address data.
*
* @retval NRF_SUCCESS If the base address was set successfully.
* @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
* @retval NRF_ERROR_INVALID_PARAM If the function failed because the address given was too close to a zero address.
* @retval NRF_ERROR_NULL If the required parameter was NULL.
*/
uint32_t nrf_esb_set_base_address_0(uint8_t const * p_addr);
/**@brief Function for setting the base address for pipe 1 to pipe 7.
*
* @param[in] p_addr Pointer to the address data.
*
* @retval NRF_SUCCESS If the base address was set successfully.
* @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
* @retval NRF_ERROR_INVALID_PARAM If the function failed because the address given was too close to a zero address.
* @retval NRF_ERROR_NULL If the required parameter was NULL.
*/
uint32_t nrf_esb_set_base_address_1(uint8_t const * p_addr);
/**@brief Function for setting the number of pipes and the pipe prefix addresses.
*
* This function configures the number of available pipes, enables the pipes,
* and sets their prefix addresses.
*
* @param[in] p_prefixes Pointer to a char array that contains the prefix for each pipe.
* @param[in] num_pipes Number of pipes. Must be less than or equal to @ref NRF_ESB_PIPE_COUNT.
*
* @retval NRF_SUCCESS If the prefix addresses were set successfully.
* @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
* @retval NRF_ERROR_NULL If a required parameter was NULL.
* @retval NRF_ERROR_INVALID_PARAM If an invalid number of pipes was given or if the address given was too close to a zero address.
*/
uint32_t nrf_esb_set_prefixes(uint8_t const * p_prefixes, uint8_t num_pipes);
/**@brief Function for enabling pipes.
*
* The @p enable_mask parameter must contain the same number of pipes as has been configured
* with @ref nrf_esb_set_prefixes. This number may not be greater than the number defined by
* @ref NRF_ESB_PIPE_COUNT
*
* @param enable_mask Bitfield mask to enable or disable pipes. Setting a bit to
* 0 disables the pipe. Setting a bit to 1 enables the pipe.
*
* @retval NRF_SUCCESS If the pipes were enabled and disabled successfully.
* @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
* @retval NRF_ERROR_INVALID_PARAM If the function failed because the address given was too close to a zero address.
*/
uint32_t nrf_esb_enable_pipes(uint8_t enable_mask);
/**@brief Function for updating the prefix for a pipe.
*
* @param pipe Pipe for which to set the prefix.
* @param prefix Prefix to set for the pipe.
*
* @retval NRF_SUCCESS If the operation completed successfully.
* @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
* @retval NRF_ERROR_INVALID_PARAM If the given pipe number was invalid or if the address given was too close to a zero address.
*/
uint32_t nrf_esb_update_prefix(uint8_t pipe, uint8_t prefix);
/** @brief Function for setting the channel to use for the radio.
*
* The module must be in an idle state to call this function. As a PTX, the
* application must wait for an idle state and as a PRX, the application must stop RX
* before changing the channel. After changing the channel, operation can be resumed.
*
* @param[in] channel Channel to use for radio.
*
* @retval NRF_SUCCESS If the operation completed successfully.
* @retval NRF_INVALID_STATE If the module is not initialized.
* @retval NRF_ERROR_BUSY If the module was not in idle state.
* @retval NRF_ERROR_INVALID_PARAM If the channel is invalid (larger than 100).
*/
uint32_t nrf_esb_set_rf_channel(uint32_t channel);
/**@brief Function for getting the current radio channel.
*
* @param[in, out] p_channel Pointer to the channel data.
*
* @retval NRF_SUCCESS If the operation completed successfully.
* @retval NRF_ERROR_NULL If the required parameter was NULL.
*/
uint32_t nrf_esb_get_rf_channel(uint32_t * p_channel);
/**@brief Function for setting the radio output power.
*
* @param[in] tx_output_power Output power.
*
* @retval NRF_SUCCESS If the operation completed successfully.
* @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
*/
uint32_t nrf_esb_set_tx_power(nrf_esb_tx_power_t tx_output_power);
/**@brief Function for setting the packet retransmit delay.
*
* @param[in] delay Delay between retransmissions.
*
* @retval NRF_SUCCESS If the operation completed successfully.
* @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
*/
uint32_t nrf_esb_set_retransmit_delay(uint16_t delay);
/**@brief Function for setting the number of retransmission attempts.
*
* @param[in] count Number of retransmissions.
*
* @retval NRF_SUCCESS If the operation completed successfully.
* @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
*/
uint32_t nrf_esb_set_retransmit_count(uint16_t count);
/**@brief Function for setting the radio bitrate.
*
* @param[in] bitrate Radio bitrate.
*
* @retval NRF_SUCCESS If the operation completed successfully.
* @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
*/
uint32_t nrf_esb_set_bitrate(nrf_esb_bitrate_t bitrate);
/**@brief Function for reusing a packet ID for a specific pipe.
*
* The ESB protocol uses a 2-bit sequence number (packet ID) to identify
* retransmitted packets. By default, the packet ID is incremented for every
* uploaded packet. Use this function to prevent this and send two different
* packets with the same packet ID.
*
* @param[in] pipe Pipe.
*
* @retval NRF_SUCCESS If the operation completed successfully.
* @retval NRF_ERROR_BUSY If the function failed because the radio is busy.
*/
uint32_t nrf_esb_reuse_pid(uint8_t pipe);
/** @} */
#ifdef __cplusplus
}
#endif
#endif // NRF_ESB

View File

@@ -0,0 +1,56 @@
/**
* Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __NRF_ESB_ERROR_CODES_H__
#define __NRF_ESB_ERROR_CODES_H__
#ifdef __cplusplus
extern "C" {
#endif
#define NRF_ERROR_BUFFER_EMPTY (0x0100)
#define NRF_ESB_ERROR_NOT_IN_RX_MODE (0x0101)
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,72 @@
/**
* Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef NRF_ESB_RESOURCES_H__
#define NRF_ESB_RESOURCES_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup nrf_esb_resources ESB resources
* @{
* @ingroup nrf_esb
*/
#ifndef ESB_ALTERNATIVE_RESOURCES
#define ESB_PPI_CHANNELS_USED 0x00000007uL /**< PPI channels used by ESB (not available to the application). */
#define ESB_TIMERS_USED 0x00000004uL /**< Timers used by ESB. */
#define ESB_SWI_USED 0x00000001uL /**< Software interrupts used by ESB. */
#else
#define ESB_PPI_CHANNELS_USED 0x00000700uL /**< PPI channels used by ESB (not available to the application). */
#define ESB_TIMERS_USED 0x00000001uL /**< Timers used by ESB. */
#define ESB_SWI_USED 0x00000002uL /**< Software interrupts used by ESB. */
#endif
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* NRF_ESB_RESOURCES_H__ */

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,37 @@
Copyright (c) 2010 - 2020, Nordic Semiconductor ASA
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form, except as embedded into a Nordic
Semiconductor ASA integrated circuit in a product or a software update for
such product, must reproduce the above copyright notice, this list of
conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
3. Neither the name of Nordic Semiconductor ASA nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
4. This software, with or without modification, must only be used with a
Nordic Semiconductor ASA integrated circuit.
5. Any software provided in binary form under this license must not be reverse
engineered, decompiled, modified and/or disassembled.
THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,168 @@
/**
* Copyright (c) 2008 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __GZP_CONFIG_H
#define __GZP_CONFIG_H
#include "nrf.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Definition of "secret key" used during "Host ID exchange".
*/
#define GZP_SECRET_KEY {1, 23, 45, 57, 26, 68, 12, 64, 13, 73, 13, 62, 26, 45, 12, 77}
//-----------------------------------------------------------------------------
/**
Definition of the first static selected pairing channel. Should be located in
the lower Nth of the channel range, where N is the size if the channel subset
selected by the application.
*/
#define GZP_CHANNEL_LOW 2
/**
Definition of the second static selected pairing channel. Should be located in
the upper Nth of the channel range, where N is the size if the channel subset
selected by the application.
*/
#define GZP_CHANNEL_HIGH 79
/**
Definition of the static "global" pairing address.
*/
#define GZP_ADDRESS 4, 6, 8, 10
/**
Reduced TX power for use during close proximity pairing.
*/
#define GZP_POWER NRF_GZLL_TX_POWER_N16_DBM
/**
Definition of pairing request timeout.
*/
#define GZP_REQ_TX_TIMEOUT 200
/**
Definition of the maximimum number of "backoff" packets (step 0) to be transmitted.
*/
#define GZP_MAX_BACKOFF_PACKETS 100
/**
Definition of the period a device shall wait before attempting to send the packet for
fetching the pairing response (step 1).
*/
#define GZP_TX_ACK_WAIT_TIMEOUT (GZP_CLOSE_PROXIMITY_BACKOFF_RX_TIMEOUT + 50)
/**
Definition of the period a device in close proximity shall back off on the pairing
address after a backoff packet has been received.
*/
#define GZP_CLOSE_PROXIMITY_BACKOFF_RX_TIMEOUT ((GZP_REQ_TX_TIMEOUT / 2) + 50)
/**
Definition of the period a device NOT in close proximity shall back off on the pairing
address after a backoff packet has been received.
*/
#define GZP_NOT_PROXIMITY_BACKOFF_RX_TIMEOUT (GZP_CLOSE_PROXIMITY_BACKOFF_RX_TIMEOUT + GZP_STEP1_RX_TIMEOUT)
/**
Definition of the time the host waits for a device to complete
transmission of the pairing request step 1 packet.
*/
#define GZP_STEP1_RX_TIMEOUT (((GZP_REQ_TX_TIMEOUT / 2) + GZP_TX_ACK_WAIT_TIMEOUT) + 50)
/**
Definition of the lowest boundary for the channel range to be used.
*/
#define GZP_CHANNEL_MIN 2
/**
Definition of the upper boundary for the channel range to be used.
*/
#define GZP_CHANNEL_MAX 80
/**
Definition of the minimum channel spacing for the channel subset generated
during pairing.
*/
#define GZP_CHANNEL_SPACING_MIN 5
/**
Non volatile memory (Flash or OTP) storage address. A device will
require GZP_DEVICE_PARAMS_STORAGE_SIZE bytes of memory, and
Host 11 bytes. When using flash memory, storage address should
be a multiple of chip page size.
*/
#define GZP_PARAMS_STORAGE_ADR 0x00001000
/**
Number of bytes available for parameter storage in Device.
It is equal to flash page size on nRF5x chips.
*/
#if defined (NRF51)
#define GZP_DEVICE_PARAMS_STORAGE_SIZE 1024
#elif defined (NRF52_SERIES)
#define GZP_DEVICE_PARAMS_STORAGE_SIZE 4096
#else
#error Chip type is undefined!
#endif
/**
Maximum Device TX payload length [bytes].
*/
#define GZP_MAX_FW_PAYLOAD_LENGTH 17
/**
Maximum Host ACK payload length [bytes].
*/
#define GZP_MAX_ACK_PAYLOAD_LENGTH 10
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,37 @@
Copyright (c) 2010 - 2020, Nordic Semiconductor ASA
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form, except as embedded into a Nordic
Semiconductor ASA integrated circuit in a product or a software update for
such product, must reproduce the above copyright notice, this list of
conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
3. Neither the name of Nordic Semiconductor ASA nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
4. This software, with or without modification, must only be used with a
Nordic Semiconductor ASA integrated circuit.
5. Any software provided in binary form under this license must not be reverse
engineered, decompiled, modified and/or disassembled.
THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,37 @@
Copyright (c) 2010 - 2020, Nordic Semiconductor ASA
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form, except as embedded into a Nordic
Semiconductor ASA integrated circuit in a product or a software update for
such product, must reproduce the above copyright notice, this list of
conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.
3. Neither the name of Nordic Semiconductor ASA nor the names of its
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
4. This software, with or without modification, must only be used with a
Nordic Semiconductor ASA integrated circuit.
5. Any software provided in binary form under this license must not be reverse
engineered, decompiled, modified and/or disassembled.
THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,937 @@
/**
* Copyright (c) 2012 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* @file
* @brief Gazell Link Layer API.
*/
#ifndef NRF_GZLL_H__
#define NRF_GZLL_H__
#include <stdbool.h>
#include "nrf.h"
#include "nrf_gzll_constants.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup gzll_02_api Gazell Link Layer
* @{
* @ingroup modules_01_gzll
* @brief Gazell Link Layer Application Programming Interface (API).
*/
/**
* @enum nrf_gzll_mode_t
* @brief Enumerator used for selecting Gazell mode.
*/
typedef enum
{
NRF_GZLL_MODE_DEVICE, ///< Device mode
NRF_GZLL_MODE_HOST, ///< Host mode
NRF_GZLL_MODE_SUSPEND, ///< Suspend mode ("disabled with timer running")
} nrf_gzll_mode_t;
/**
* @enum nrf_gzll_device_channel_selection_policy_t
* @brief Enumerator used for selecting Gazell Device channel
* selection policy.
*/
typedef enum
{
NRF_GZLL_DEVICE_CHANNEL_SELECTION_POLICY_USE_SUCCESSFUL, ///< Start on previous successful channel
NRF_GZLL_DEVICE_CHANNEL_SELECTION_POLICY_USE_CURRENT, ///< Start on channel currently monitored by Host
} nrf_gzll_device_channel_selection_policy_t;
/**
* @enum nrf_gzll_tx_power_t
* @brief Enumerator used for selecting the transmit (TX) power.
*/
typedef enum
{
NRF_GZLL_TX_POWER_4_DBM, ///< 4 dBm transmit power.
NRF_GZLL_TX_POWER_0_DBM, ///< 0 dBm transmit power.
NRF_GZLL_TX_POWER_N4_DBM, ///< -4 dBm transmit power.
NRF_GZLL_TX_POWER_N8_DBM, ///< -8 dBm transmit power.
NRF_GZLL_TX_POWER_N12_DBM, ///< -12 dBm transmit power.
NRF_GZLL_TX_POWER_N16_DBM, ///< -16 dBm transmit power.
NRF_GZLL_TX_POWER_N20_DBM ///< -20 dBm transmit power.
} nrf_gzll_tx_power_t;
/**
* @enum nrf_gzll_datarate_t
* @brief Enumerator used for selecting the radio datarate.
*/
typedef enum
{
#ifdef NRF51
NRF_GZLL_DATARATE_250KBIT = 0, ///< 250 Kbps datarate, available only for the nRF51.
#endif
NRF_GZLL_DATARATE_1MBIT = 1, ///< 1 Mbps datarate.
NRF_GZLL_DATARATE_2MBIT = 2 ///< 2 Mbps datarate.
} nrf_gzll_datarate_t;
/**
* @enum nrf_gzll_xosc_ctl_t
* @brief Enumerator used for specifying whether switching the
* external 16 MHz oscillator on/off shall be handled automatically
* inside Gazell or manually by the application.
*/
typedef enum
{
NRF_GZLL_XOSC_CTL_AUTO, ///< Switch XOSC on/off automatically
NRF_GZLL_XOSC_CTL_MANUAL ///< Switch XOSC on/off manually
} nrf_gzll_xosc_ctl_t;
/**
* @enum nrf_gzll_error_code_t
* @brief Enumerator used for error codes for Gazell API functions
*/
typedef enum
{
NRF_GZLL_ERROR_CODE_NO_ERROR = 0, ///< No error has been detected.
NRF_GZLL_ERROR_CODE_FAILED_TO_INITIALIZE = 1, ///< The function NRF_GZLL_init failed.
NRF_GZLL_ERROR_CODE_ATTEMPTED_TO_CONFIGURE_WHEN_ENABLED = 2, ///< A call to a configuration 'set' function was made while Gazell was enabled.
NRF_GZLL_ERROR_CODE_POINTER_IS_NULL = 3, ///< A null pointer was given as an input to a function.
NRF_GZLL_ERROR_CODE_INVALID_PIPE = 4, ///< An invalid pipe number was given as an input to a function.
NRF_GZLL_ERROR_CODE_INVALID_MODE = 5, ///< An invalid value for the nrf_gzll_mode_t enumerator was given as input to a function.
NRF_GZLL_ERROR_CODE_INVALID_PAYLOAD_LENGTH = 6, ///< An invalid payload length was given as an input to a function.
NRF_GZLL_ERROR_CODE_INVALID_CHANNEL_TABLE_SIZE = 7, ///< An invalid channel table size was given as an input to a function.
NRF_GZLL_ERROR_CODE_INSUFFICIENT_PACKETS_AVAILABLE = 8, ///< There are insufficient packets in the Gazell memory pool to successfully execute the operation.
NRF_GZLL_ERROR_CODE_ATTEMPTED_TO_ADD_TO_FULL_FIFO = 9, ///< There is insufficient space in the TX FIFO for the data packet.
NRF_GZLL_ERROR_CODE_NO_SPACE_IN_RX_FIFO_FOR_ACK = 10, ///< There is insufficient space in the RX FIFO for the ACK.
NRF_GZLL_ERROR_CODE_ATTEMPTED_TO_FETCH_FROM_EMPTY_FIFO = 11, ///< Attempted to fetch a packet from an empty FIFO. Use the functions nrf_gzll_get_tx_fifo_packet_count() or nrf_gzll_get_rx_fifo_packet_count()
NRF_GZLL_ERROR_CODE_ATTEMPTED_TO_FLUSH_WHEN_ENABLED = 12, ///< Attempted to fetch a packet from an empty FIFO. Use the functions nrf_gzll_get_tx_fifo_packet_count() or nrf_gzll_get_rx_fifo_packet_count()
NRF_GZLL_ERROR_CODE_INVALID_PARAMETER = 14, ///< Attempted to set a variable which was not valid.
NRF_GZLL_ERROR_CODE_INTERNAL_ASSERT_OCCURRED = 15, ///< An internal assert occurred.
NRF_GZLL_ERROR_CODE_CALLBACK_NOT_IMPLEMENTED = 16, ///< A callback was called but not implemented by the application.
NRF_GZLL_ERROR_CODE_INVALID_ADDRESS = 17, ///< Invalid pipe 0 address detected, see Anomaly 107 at nRF52832 errata document.
NRF_GZLL_ERROR_CODE_NUMBER_OF_ERROR_CODES = 18, ///< Number of possible error codes.
} nrf_gzll_error_code_t;
/**
* @struct nrf_gzll_device_tx_info_t;
* @brief Data structure containing information about the last packet
* transmission.
*/
typedef struct
{
bool payload_received_in_ack; ///< A payload was received in the ACK.
uint16_t num_tx_attempts; ///< Number of attempts used on previous Device packet transmission.
uint16_t num_channel_switches; ///< Number of channel switches needed during previous packet transmission.
int8_t rssi; ///< Received signal strength indicator in dBm. @sa nrf_gzll_enable_rssi().
uint8_t rf_channel; ///< Channel on which packet has been transmitted.
} nrf_gzll_device_tx_info_t;
/**
* @struct nrf_gzll_host_rx_info_t;
* @brief Data structure containing information about the last packet
* received.
*/
typedef struct
{
bool packet_removed_from_tx_fifo; ///< A payload was received in the ACK.
int8_t rssi; ///< Received signal strength indicator in dBm. @sa nrf_gzll_enable_rssi().
uint8_t rf_channel; ///< Channel on which packet has been received.
} nrf_gzll_host_rx_info_t;
typedef struct
{
uint32_t packets_num; ///< Number of succesfully transmitted packets
uint32_t timeouts_num; ///< Total timeouts number
uint32_t channel_timeouts[NRF_GZLL_CONST_MAX_CHANNEL_TABLE_SIZE]; ///< Transmission timeouts per channel
uint32_t channel_packets[NRF_GZLL_CONST_MAX_CHANNEL_TABLE_SIZE]; ///< Succesfully transmitted packets per channel
} nrf_gzll_tx_statistics_t;
/**< Transmission timeout callback function definition */
typedef void (*nrf_gzll_tx_timeout_callback)(uint32_t pipe, uint8_t rf_channel);
/**< Transmission CRC failure callback function definition */
typedef void (*nrf_gzll_crc_failure_callback)(uint32_t pipe, uint8_t rf_channel);
#if defined(NRF52_SERIES) || defined(__SDK_DOXYGEN__)
/**
* @brief Data structure holding external front
* end control configuration.
*/
typedef struct
{
bool pa_enabled; ///< Flag indicating if PA control is enabled.
bool pa_active_high; ///< Flag indicating if PA is active in high input state.
uint8_t pa_gpio_pin; ///< Number of output pin used for PA control.
uint8_t pa_gpiote_channel; ///< Number of GPIOTE channel used for PA control.
bool lna_enabled; ///< Flag indicating if LNA control is enabled.
bool lna_active_high; ///< Flag indicating if LNA is active in high input state.
uint8_t lna_gpio_pin; ///< Number of output pin used for LNA control.
uint8_t lna_gpiote_channel; ///< Number of GPIOTE channel used for LNA control.
NRF_TIMER_Type * timer; ///< Pointer to the TIMER instance.
uint8_t ppi_channels[NRF_GZLL_PA_LNA_PPI_CHANNELS_NUM]; ///< PPI channels used to control front end.
uint8_t ramp_up_time; ///< Determines how early should the PA/LNA be turned one before RADIO activity. Should be less than @ref NRF_GZLL_PA_LNA_MAX_RAMP_UP_TIME.
} nrf_gzll_pa_lna_cfg_t;
#endif
/******************************************************************************/
/** @name General API functions
* @{ */
/******************************************************************************/
/**
* @brief Initialize Gazell.
*
* @param mode The mode to initialize Gazell in.
*
* @retval true if Gazell initialized.
* @retval false if Gazell failed to initialize.
*/
bool nrf_gzll_init(nrf_gzll_mode_t mode);
/**
* @brief Enable Gazell.
*
* When enabled the behaviour described for the current Gazell Link Layer mode
* will apply.
*
* @retval false if nrf_gzll_init has not previously been called or invalid address
* has been set - see Anomaly 107 at nRF52832 errata document.
*/
bool nrf_gzll_enable(void);
/**
* @brief Disable Gazell.
*
* When calling this function the Gazell Link Layer will begin disabling,
* and will be fully disabled when Gazell calls nrf_gzll_disabled().
* If there are any pending notifications, or if any new notifications are
* being added to the internal notification queue while Gazell is disabling,
* these will be sent to the application before Gazell is fully disabled.
*
* After Gazell has been fully disabled, no more notifications will be sent to
* the application.
*/
void nrf_gzll_disable(void);
/** Check whether Gazell is enabled or disabled.
*
* @retval true If Gazell is enabled.
* @retval false If Gazell is disabled.
*/
bool nrf_gzll_is_enabled(void);
/** @} */
/******************************************************************************/
/** @name Device mode callback functions
* @{ */
/******************************************************************************/
/**
* @brief ACK received callback (Device mode only).
*
* This callback is made when the Device receives an ACK (acknowledgement)
* packet.
* @sa nrf_gzll_ack_payload_received.
*
* @param pipe is the pipe on which an ACK packet was received.
* @param tx_info struct used to indicate whether a payload was received in the
* ack, as well as the number of TX attempts and channel switches required.
*/
void nrf_gzll_device_tx_success(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info);
/**
* @brief Transmission failed callback (Device mode only).
*
* This callback is made when a packet does not receive an ACK after
* nrf_gzll_max_retries is reached. The packet is deleted by Gazell.
*
* @param pipe is the pipe on which the transmission failed.
* @param tx_info struct used to indicate whether a payload was received
* in the ack, as well as RSSI and the number of TX attempts and
* channel switches required.
*/
void nrf_gzll_device_tx_failed(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info);
/** @} */
/******************************************************************************/
/** @name Host mode callback functions
* @{ */
/******************************************************************************/
/**
* @brief Data packet received callback (Host mode only).
*
* This callback is made when a Host receives a data packet from a Device.
*
* @param pipe is the pipe on which the data packet was received.
* @param rx_info struct used to indicate whether a payload was removed from the
* pipe's TX FIFO, as well as RSSI.
*/
void nrf_gzll_host_rx_data_ready(uint32_t pipe, nrf_gzll_host_rx_info_t rx_info);
/** @} */
/******************************************************************************/
/** @name Callback functions for both Device and Host mode
* @{ */
/******************************************************************************/
/**
* @brief Disabled callback.
*
* This is called after Gazell enters the disabled state.
* There is no further CPU use by Gazell, the radio is disabled and the timer is
* powered down.
*/
void nrf_gzll_disabled(void);
/**
* @brief Mode changed callbackl.
*
* This function is called after the Gazell mode has been changed.
* This function can only be called when Gazell is enabled.
*/
void nrf_gzll_mode_changed(void);
/** @} */
/******************************************************************************/
/** @name Packet transmission and receiving functions
* @{ */
/******************************************************************************/
/**
* @brief Add a packet to the tail of the TX FIFO.
*
* In Device mode, the packet will be added.
* In Host mode, the payload will be piggybacked onto an ACK.
*
* @param pipe Pipe to which to add the payload. This value must be < NRF_GZLL_CONST_PIPE_COUNT.
* @param p_payload Pointer to the payload.
* @param length Number of bytes of the payload to transmit
* (0 to NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH).
*
* @retval true if the packet was successfully added to the TX FIFO.
* @retval false if unsuccessful, check nrf_gzll_error_code_t for more information.
*/
bool nrf_gzll_add_packet_to_tx_fifo(uint32_t pipe, uint8_t * p_payload, uint32_t length);
/**
* @brief Fetch a packet from the head of the RX FIFO.
*
* @param pipe Pipe from which to fetch the payload. This value must be < NRF_GZLL_CONST_PIPE_COUNT.
* @param p_payload Pointer to copy the payload to.
* @param p_length Length must be at least as large as the the number of bytes
* in the received payload length.
*
* @retval true If the fetch was successful.
* @retval false If unsuccessful, check nrf_gzll_error_code_t for more information.
*/
bool nrf_gzll_fetch_packet_from_rx_fifo(uint32_t pipe, uint8_t * p_payload, uint32_t * p_length);
/**
* @brief Get the number of packets in the TX FIFO on a specific pipe.
*
* @param pipe The pipe for which to check. This value must be < NRF_GZLL_CONST_PIPE_COUNT.
*
* @retval >=0 The number of packets in the TX FIFO for the pipe.
* @retval -1 If the pipe number is invalid.
*/
int32_t nrf_gzll_get_tx_fifo_packet_count(uint32_t pipe);
/**
* @brief Get the number of packets in the RX FIFO on a specific pipe.
*
* @param pipe The pipe for which to check. This value must be < NRF_GZLL_CONST_PIPE_COUNT.
* @retval >=0 The number of packets in the RX FIFO for the pipe.
* @retval -1 If the pipe number is invalid.
*/
int32_t nrf_gzll_get_rx_fifo_packet_count(uint32_t pipe);
/**
* @brief Get the total number of packets residing in all TX and RX FIFOs.
*
* Can be used to check against NRF_GZLL_CONST_MAX_TOTAL_PACKETS to
* determine if there is free space in the memory pool for more packets.
*
* @return The number of packets residing in all TX and RX FIFOs.
*/
uint32_t nrf_gzll_get_total_allocated_packet_count(void);
/**
* @brief Check if adding a packet to a pipe's TX FIFO should be successful.
*
* Checks if there is another space in the pipe's TX and RX FIFOs
* as well as enough overall space in the packet pool.
*
* @param pipe The pip for which to check. This value must be < NRF_GZLL_CONST_PIPE_COUNT.
*
* @retval true If there is another space.
* @retval false If there is not enough space, or the pipe is invalid.
*/
bool nrf_gzll_ok_to_add_packet_to_tx_fifo(uint32_t pipe);
/**
* @brief Flush the RX FIFO for a specific pipe.
*
* Delete all the packets and free the memory of the TX FIFO for a
* specific pipe.
*
* Note that it is not allowed to flush a TX FIFO when
* Gazell is enabled.
*
* @param pipe is the pipe for which to flush. This value must be < NRF_GZLL_CONST_PIPE_COUNT.
* @retval true if the pipe was flushed.
* @retval false if the pipe was not flushed.
*/
bool nrf_gzll_flush_tx_fifo(uint32_t pipe);
/**
* @brief Flush the RX FIFO for a specific pipe.
*
* Delete all the packets and free the memory of the RX FIFO for a
* specific pipe.
*
* @param pipe is the pipe for which to flush. This value must be < NRF_GZLL_CONST_PIPE_COUNT.
* @retval true if the pipe was flushed.
* @retval false if the pipe was not flushed.
*/
bool nrf_gzll_flush_rx_fifo(uint32_t pipe);
/**
* @brief Function for enabling transmission statistics.
*
* @param p_statistics Pointer to the statistics structure.
*
* @return True if channel statistics has been enabled, false otherwise.
*/
bool nrf_gzll_tx_statistics_enable(nrf_gzll_tx_statistics_t * p_statistics);
/**
* @brief Function for disabling transmission statistics.
*/
void nrf_gzll_tx_statistics_disable(void);
/**
* @brief Function for obtaining number of transmission timeouts for specific channel.
*
* @param[in] channel_index Channel index in channel table.
* @param[out] p_timeouts Pointer for the result.
*
* @return True in case of success, false otherwise.
*/
bool nrf_gzll_get_channel_timeouts(uint8_t channel_index, uint32_t *p_timeouts);
/**
* @brief Function for clearing transmission statistic structure.
*/
void nrf_gzll_reset_tx_statistics(void);
/** @} */
/******************************************************************************/
/** @name Configuration functions
*
* Configuration 'set' functions may only be called while Gazell is disabled. The
* new parameter comes into effect when Gazell is enabled again.
*
* Configuration 'get' functions may be called at any time.
*
* @{ */
/******************************************************************************/
/**
* @brief Function for registering callback to be called on the transmission timeout.
*/
void nrf_gzll_tx_timeout_callback_register(nrf_gzll_tx_timeout_callback callback);
/**
* @brief Function for registering callback to be called on the packet CRC failure.
*/
void nrf_gzll_crc_failure_callback_register(nrf_gzll_crc_failure_callback callback);
/**
* @brief Set the mode.
*
* @param mode The mode to be used.
* See nrf_gzll_mode_t for a list of valid modes.
*
* It is allowed to change mode when Gazell is enabled. If the mode is
* being changed while Gazell is enabled, the mode will not change right away.
* In this case the callback function nrf_gzll_mode_changed() will be called
* after the mdoe has changed.
*
* @retval true If the parameter was set.
*/
bool nrf_gzll_set_mode(nrf_gzll_mode_t mode);
/**
* @brief Get function counterpart to nrf_gzll_set_mode().
*
* @return The current mode.
*/
nrf_gzll_mode_t nrf_gzll_get_mode(void);
/**
* @brief Set the base address for pipe 0.
*
* The full on-air address for each pipe is composed of a multi-byte base address
* prepended to a prefix byte.
*
* For packets to be received correctly, the most significant byte of
* the base address should not be an alternating sequence of 0s and 1s i.e.
* it should not be 0x55 or 0xAA.
*
* @param base_address The 4 byte base address. All bytes are used.
*
* @note Due to the nRF52 Anomaly 107, pipe 0 address should not have
* both prefix and two LSB of base address set to 0.
*
* @retval true If the parameter was set.
* @return false If Gazell was enabled.
*/
bool nrf_gzll_set_base_address_0(uint32_t base_address);
/**
* @brief Get function counterpart to nrf_gzll_set_base_address_0().
*
* @return Base address 0.
*/
uint32_t nrf_gzll_get_base_address_0(void);
/**
* @brief Set the base address for pipes 1-7.
*
* Pipes 1 through 7 share base_address_1. @sa nrf_gzll_set_base_address_0.
*
* @param base_address The 4 byte base address.
*
* @retval true If the parameter was set.
* @retval false If Gazell was enabled.
*/
bool nrf_gzll_set_base_address_1(uint32_t base_address);
/**
* @brief Get function counterpart to nrf_gzll_set_base_address_1().
*
* @return Base address 1.
*/
uint32_t nrf_gzll_get_base_address_1(void);
/**
* @brief Set the address prefix byte for a specific pipe.
*
* Each pipe should have its own unique prefix byte.
*
* @param pipe The pipe that the address should apply to.
* This value must be < NRF_GZLL_CONST_PIPE_COUNT.
* @param address_prefix_byte The address prefix byte.
*
* @note Due to the Anomaly 107, pipe 0 address should not have
* both prefix and two LSB of base address set to 0.
*
* @retval true If the parameter was set.
* @retval false If Gazell was enabled, or if the pipe was invalid.
*/
bool nrf_gzll_set_address_prefix_byte(uint32_t pipe, uint8_t address_prefix_byte);
/**
* @brief Get function counterpart to nrf_gzll_set_address_prefix_byte().
*
* @param pipe The pipe for which to get the address.
* This value must be < NRF_GZLL_CONST_PIPE_COUNT.
* @param p_out_address_prefix_byte The pointer in which to return the
* address prefix byte.
*
* @retval true If the parameter was returned.
* @retval false If Gazell was enabled, the pipe was invalid or
* out_address was a NULL pointer.
*/
bool nrf_gzll_get_address_prefix_byte(uint32_t pipe, uint8_t * p_out_address_prefix_byte);
/**
* @brief Set which pipes shall listen for packets in Host mode.
*
* This value is a bitmap, and each bit corresponds to a given pipe number.
* Bit 0 set to "1" enables pipes 0, bit 1 set to "1" enables pipe 1
* and so forth.
* The maximum number of pipes is defined by NRF_GZLL_CONST_PIPE_COUNT.
*
* @param pipes A bitmap specifying which pipes to monitor.
*
* @retval true If the parameter was set.
* @retval false If Gazell was enabled.
*/
bool nrf_gzll_set_rx_pipes_enabled(uint32_t pipes);
/**
* @brief Get function counterpart to nrf_gzll_set_rx_pipes_enabled().
*
* @return Bitmap holding the current enabled pipes.
*/
uint32_t nrf_gzll_get_rx_pipes_enabled(void);
/**
* @brief Set the timeslot period.
*
* The length in microseconds of a Gazell link layer timeslot.
*
* The minimum value of the timeslot period is dependent of the
* radio data rate (@sa nrf_gzll_set_datarate()).
*
* - For NRF_GZLL_DATARATE_2MBIT the timeslot period must be >= 600 us.
* - For NRF_GZLL_DATARATE_1MBIT the timeslot period must be >= 900 us.
* - For NRF_GZLL_DATARATE_250KBIT the timeslot period must be >= 2700 us.
*
* @param period_us The timeslot period in microseconds.
*
* @retval true If the parameter was set.
* @retval false If Gazell was enabled.
*/
bool nrf_gzll_set_timeslot_period(uint32_t period_us);
/**
* @brief Get function counterpart to nrf_gzll_get_timeslot_period().
*
* @return The current timeslot period.
*/
uint32_t nrf_gzll_get_timeslot_period(void);
/**
* @brief Set the Device channel selection policy
*
* The policy determines the initial channel when starting a new packet.
* transmission.
*
* @param policy The channel selection policy.
*
* @arg NRF_GZLL_DEVICE_CHANNEL_SELECTION_POLICY_USE_SUCCESSFUL specifies
* that a new packet transmission always shall use the previous
* successful channel from the channel table. If Gazell is "in sync", Gazell
* will wait until this channel is being monitored by the Host before starting
* the transmission.
*
* @arg NRF_GZLL_DEVICE_CHANNEL_SELECTION_POLICY_USE_CURRENT specifies that
* Gazell shall transmit on the channel that is currently being monitored by the
* Host. This parameter is only used when Gazell is "in sync". When "out of" sync,
* Gazell will always start using the "previous successful" channel.
*
* @retval true If the parameter was set.
* @retval false If Gazell was enabled or the policy was invalid.
*/
bool nrf_gzll_set_device_channel_selection_policy(nrf_gzll_device_channel_selection_policy_t policy);
/**
* @brief Get function counterpart to nrf_gzll_set_device_channel_selection_policy().
*
* @return the Device channel selection policy.
*/
nrf_gzll_device_channel_selection_policy_t nrf_gzll_get_device_channel_selection_policy(void);
/**
* @brief Set the number of timeslots that Gazell shall
* reside on a single channel before switching to another channel.
*
* This parameter applies in Host mode and for a Device that is
* in the "in sync" state.
*
* Since the Device and Host can not be in perfect synchronization, a
* transmission should overlap to adjacent timeslots on the Host.
* Therefore this value should be at least 2.
*
* @sa nrf_gzll_set_timeslots_per_channel_when_device_out_of_sync
*
* @param timeslots The number of timeslots to reside on
* each channel before channel switch.
*
* @retval true If the parameter was set.
* @retval false If Gazell was enabled.
*/
bool nrf_gzll_set_timeslots_per_channel(uint32_t timeslots);
/**
* @brief Get function counterpart to nrf_gzll_set_timeslots_per_channel().
*
* @return The current number of timeslots.
*/
uint32_t nrf_gzll_get_timeslots_per_channel(void);
/**
* @brief Set the number of timeslots that a Gazell shall
* reside on a single channel before switching to another channel when
* in the "out of sync" state.
*
* This value should be set so that the Device transmits on one channel
* while the Host goes through a full channel rotation, i.e.,
* channel_table_size*timeslots_per_channel.
* This ensures that the channels on the Device and Host will coincide
* at some point.
* Further increasing the value has been observed to provide better performance
* in the presence of interferers.
*
* @param timeslots The number of timeslots to reside on
* each channel before channel switch.
*
* @retval true If the parameter was set.
* @retval false If Gazell was enabled.
*/
bool nrf_gzll_set_timeslots_per_channel_when_device_out_of_sync(uint32_t timeslots);
/**
* @brief Get function counterpart to
* nrf_gzll_set_timeslots_per_channel_when_device_out_of_sync().
*
* @return The current number of timeslots.
*/
uint32_t nrf_gzll_get_timeslots_per_channel_when_device_out_of_sync(void);
/**
* @brief Set the number of timeslots after a successful
* reception of a Device or Host packet that the Gazell Link Layer shall assume
* that the link is synchronized. A value of 0 implies that the
* link is always out of sync.
*
* @param lifetime The sync lifetime in number of timeslots.
*
* @retval true If the sync lifetime was set.
* @retval false If Gazell was enabled.
*/
bool nrf_gzll_set_sync_lifetime(uint32_t lifetime);
/**
* @brief Get function counterpart to nrf_gzll_set_sync_lifetime().
*
* @return The sync lifetime measured in number of timeslots.
*/
uint32_t nrf_gzll_get_sync_lifetime(void);
/**
* @brief Set the maximum number of TX attempts
* that can be used for a single packet.
*
* After the maximum number of attempts have been spent without
* receiving any ACK from the Host, the transmission will be terminated
* and the nrf_gzll_device_tx_failed() callback will be called. A zero
* value of the function parameter implies the infinite number of TX attempts.
*
* @param max_tx_attempts The maximum number of TX attempts.
*/
void nrf_gzll_set_max_tx_attempts(uint16_t max_tx_attempts);
/**
* @brief Get function counterpart to nrf_gzll_set_max_tx_attempts().
*
* @return The current max Device TX attempts.
*/
uint16_t nrf_gzll_get_max_tx_attempts(void);
/**
* @brief Set the table of Radio Frequency (RF) channels.
*
* The valid channels are in the range 0 <= channel <= 125, where the
* actual centre frequency is (2400 + channel) MHz.
* The maximum channel table size is defined by
* NRF_GZLL_CONST_MAX_CHANNEL_TABLE_SIZE.
*
* @param p_channel_table Pointer to the channel table.
* @param size The size of the channel table.
*
* @retval true If the channel table was set.
* @retval false If Gazell was enabled, or the channel_table pointer was NULL,
* or the size was invalid.
*/
bool nrf_gzll_set_channel_table(uint8_t * p_channel_table, uint32_t size);
/**
* @brief Get the table of Radio Frequency (RF) channels.
*
* @param p_channel_table Pointer to copy the channel table to.
* @param p_size Pointer to copy the size of the channel table to.
* The value already at size must be at least the size
* of the channel table.
*
* @retval true If the channel table was copied to channel_table.
* @retval false If the channel_table pointer was NULL,
* or the size was not large enough.
*/
bool nrf_gzll_get_channel_table(uint8_t * p_channel_table, uint32_t * p_size);
/**
* @brief Get the current channel table size.
*
* @return The current channel table size.
*/
uint32_t nrf_gzll_get_channel_table_size(void);
/**
* @brief Set the radio TX power.
*
* @param tx_power TX power.
*
* @retval true If the parameter was set.
* @retval false If the TX power was invalid.
*/
bool nrf_gzll_set_tx_power(nrf_gzll_tx_power_t tx_power);
/**
* @brief Get function counterpart to nrf_gzll_set_tx_power().
*
* @return The current TX power.
*/
nrf_gzll_tx_power_t nrf_gzll_get_tx_power(void);
/**
* @brief Set the radio datarate.
*
* @param data_rate Datarate.
*
* @retval true If the parameter was set.
* @retval false If Gazell was enabled or the datarate was invalid.
*/
bool nrf_gzll_set_datarate(nrf_gzll_datarate_t data_rate);
/**
* @brief Get function counterpart to nrf_gzll_set_datarate().
*
* @return The current datarate.
*/
nrf_gzll_datarate_t nrf_gzll_get_datarate(void);
/**
* @brief Set whether start/stop of external oscillator (XOSC) shall be handled
* automatically inside Gazell or manually by the application.
*
* When controlling the XOSC manually from the application it is
* required that the XOSC is started before Gazell is enabled.
*
* When start/stop of the XOSC is handled automatically by Gazell,
* the XOSC will only be running when needed, that is when the radio
* is being used or when Gazell needs to maintain synchronization.
*
* It is required that the XOSC is started in order for the radio to be
* able to send or receive any packets.
*
* @param xosc_ctl setting for XOSC control.
*
* @retval true if the parameter was set.
* @retval false if Gazell was enabled or the xosc_ctl value was invalid.
*/
bool nrf_gzll_set_xosc_ctl(nrf_gzll_xosc_ctl_t xosc_ctl);
/**
* Get function counterpart for nrf_gzll_set_xosc_ctl();
*
* @return The XOSC control setting.
*/
nrf_gzll_xosc_ctl_t nrf_gzll_get_xosc_ctl(void);
/**
* @brief Set Gazell to disable automatically after a certain number of timeslot ticks.
*
* @param num_ticks Number of timeslot ticks.
*
*/
void nrf_gzll_set_auto_disable(uint32_t num_ticks);
#if defined(NRF52_SERIES) || defined(__SDK_DOXYGEN__)
/**
* @brief Set up external front end control.
*
* @param p_pa_lna_cfg Pointer to the configuration struct.
*/
bool nrf_gzll_set_pa_lna_cfg(nrf_gzll_pa_lna_cfg_t const * p_pa_lna_cfg);
#endif
/**
* @brief Get the number of timeslot ticks that have occurred since
* nrf_gzll_init() was called.
*
* @return Number of timeslot ticks.
*
*/
uint32_t nrf_gzll_get_tick_count(void);
/**
* @brief Clear the internal timeslot tick count variable that is read
* by nrf_gzll_get_tick_count().
*
*/
void nrf_gzll_clear_tick_count(void);
/** @} */
/******************************************************************************/
/** @name Error handling functions
* @{ */
/******************************************************************************/
/**
* @brief Gets the Gazell error code.
*
* @return The current error code.
*/
nrf_gzll_error_code_t nrf_gzll_get_error_code(void);
/**
* @brief Reset the Gazell error code.
*
* The error code is reset to NRF_GZLL_ERROR_CODE_NO_ERRROR.
*/
void nrf_gzll_reset_error_code(void);
/** @} */
/** @} */
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,188 @@
/**
* Copyright (c) 2011 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* @file
* @brief Gazell Link Layer constants and default values.
*
* NOTE! Changing values here has no effect. They are only provided as a reference.
*/
#ifndef NRF_GZLL_CONSTANTS_H__
#define NRF_GZLL_CONSTANTS_H__
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup gzll_02_api
* @{
*/
/*****************************************************************************/
/** @name Hardware resources used by Gazell */
/*****************************************************************************/
#define NRF_GZLL_HIGH_IRQ_PRIORITY 0 ///< Interrupt priority the Gazell timer and the radio
#define NRF_GZLL_LOW_IRQ_PRIORITY 1 ///< Interrupt priority for Gazell callback functions.
#ifndef USE_SD_HW_RESOURCES
#define NRF_GZLL_SWI_IRQn SWI0_IRQn ///< Software interrupt # used for callback functions.
#define NRF_GZLL_SWI_IRQ_HANDLER SWI0_IRQHandler ///< Software interrupt handler used for callback functions.
#define NRF_GZLL_TIMER NRF_TIMER2 ///< Timer to be used as flywheel timer.
#define NRF_GZLL_TIMER_IRQn TIMER2_IRQn ///< Interrupt # for the timer.
#define NRF_GZLL_TIMER_IRQ_HANDLER TIMER2_IRQHandler ///< Interrupt handler for the timer.
// In addition, Gazell uses the radio peripheral and radio interrupts.
/*
* PPI configuration
*/
#define NRF_GZLL_PPI_EEP0 (NRF_PPI->CH0_EEP) ///< Gazell PPI event endpoint 0
#define NRF_GZLL_PPI_TEP0 (NRF_PPI->CH0_TEP) ///< Gazell PPI task endpoint 0
#define NRF_GZLL_PPI_EEP1 (NRF_PPI->CH1_EEP) ///< Gazell PPI event endpoint 1
#define NRF_GZLL_PPI_TEP1 (NRF_PPI->CH1_TEP) ///< Gazell PPI task endpoint 1
#define NRF_GZLL_PPI_EEP2 (NRF_PPI->CH2_EEP) ///< Gazell PPI event endpoint 2
#define NRF_GZLL_PPI_TEP2 (NRF_PPI->CH2_TEP) ///< Gazell PPI task endpoint 2
#define NRF_GZLL_PPI_CHEN_MSK_0_AND_1 (0x03) ///< Channel enable/disable mask for PPI endpoint 0 and 1.
#define NRF_GZLL_PPI_CHEN_MSK_2 (0x04) ///< Channel enable/disable mask for PPI endpoint 2.
#else
#define NRF_GZLL_SWI_IRQn SWI1_IRQn ///< Software interrupt # used for callback functions.
#define NRF_GZLL_SWI_IRQ_HANDLER SWI1_IRQHandler ///< Software interrupt handler used for callback functions.
#define NRF_GZLL_TIMER NRF_TIMER0 ///< Timer to be used as flywheel timer.
#define NRF_GZLL_TIMER_PERPOWER_Msk POWER_PERPOWER_TIMER0_Msk ///< PERPOWER mask for the timer.
#define NRF_GZLL_TIMER_IRQn TIMER0_IRQn ///< Interrupt # for the timer.
#define NRF_GZLL_TIMER_IRQ_HANDLER TIMER0_IRQHandler ///< Interrupt handler for the timer.
// In addition, Gazell uses the radio peripheral and radio interrupts.
/*
* PPI configuration
*/
#define NRF_GZLL_PPI_EEP0 (NRF_PPI->CH8_EEP) ///< Gazell PPI event endpoint 0
#define NRF_GZLL_PPI_TEP0 (NRF_PPI->CH8_TEP) ///< Gazell PPI task endpoint 0
#define NRF_GZLL_PPI_EEP1 (NRF_PPI->CH9_EEP) ///< Gazell PPI event endpoint 1
#define NRF_GZLL_PPI_TEP1 (NRF_PPI->CH9_TEP) ///< Gazell PPI task endpoint 1
#define NRF_GZLL_PPI_EEP2 (NRF_PPI->CH10_EEP) ///< Gazell PPI event endpoint 2
#define NRF_GZLL_PPI_TEP2 (NRF_PPI->CH10_TEP) ///< Gazell PPI task endpoint 2
#define NRF_GZLL_PPI_CHEN_MSK_0_AND_1 (0x300) ///< Channel enable/disable mask for PPI endpoint 0 and 1.
#define NRF_GZLL_PPI_CHEN_MSK_2 (0x400) ///< Channel enable/disable mask for PPI endpoint 2.
#endif
/** @} */
/*****************************************************************************/
/** @name Constant pipe and FIFO configuration */
/*****************************************************************************/
#define NRF_GZLL_CONST_PIPE_COUNT 8 ///< Number of TX pipes (at least one for each Device-Host pairs).
#define NRF_GZLL_CONST_FIFO_LENGTH 3 ///< Maximum number of packets allowed in a TX or RX FIFO.
#define NRF_GZLL_CONST_MAX_TOTAL_PACKETS 6 ///< Maximum number of packets available for reservation at any one time.
#define NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH 32 ///< Maximum allowed payload length in bytes.
#define NRF_GZLL_CONST_CALLBACK_QUEUE_LENGTH 10 ///< Maximum number of notifications allowed in the callback queue.
/** @} */
/*****************************************************************************/
/** @name Default radio configuration */
/*****************************************************************************/
#define NRF_GZLL_DEFAULT_TX_POWER NRF_GZLL_TX_POWER_0_DBM ///< Default TX power.
#define NRF_GZLL_DEFAULT_DATARATE NRF_GZLL_DATARATE_2MBIT ///< Default data rate.
#define NRF_GZLL_DEFAULT_CHANNEL_TABLE {4, 25, 42, 63, 77} ///< Default channel table.
#define NRF_GZLL_DEFAULT_CHANNEL_TABLE_SIZE 5 ///< Default channel table size.
#define NRF_GZLL_CONST_MAX_CHANNEL_TABLE_SIZE 16 ///< Maximum channel table size allowed by Gazell.
/** @} */
/*****************************************************************************/
/** @name Default Address configuration */
/*****************************************************************************/
/*
Corresponds to Legacy nRFgo SDK Gazell config:
#define GZLL_DEFAULT_ADDRESS_PIPE0 {0x01, 0x04, 0x07, 0x0A, 0x0D}
#define GZLL_DEFAULT_ADDRESS_PIPE1 {0x02, 0x05, 0x08, 0x0B, 0x0E}
#define GZLL_DEFAULT_ADDRESS_PIPE2 3
#define GZLL_DEFAULT_ADDRESS_PIPE3 4
#define GZLL_DEFAULT_ADDRESS_PIPE4 5
#define GZLL_DEFAULT_ADDRESS_PIPE5 6
*/
#define NRF_GZLL_DEFAULT_FULL_ADDRESS_PIPE0 {0x01, 0x04, 0x07, 0x0A, 0x0D} ///< Corresponding legacy Gazell pipe 0 address.
#define NRF_GZLL_DEFAULT_BASE_ADDRESS_0 0x0D0A0704 ///< Default base address 0.
#define NRF_GZLL_DEFAULT_BASE_ADDRESS_1 0x0E0B0805 ///< Default base address 1.
#define NRF_GZLL_DEFAULT_PREFIX_BYTE_0 1 ///< Default prefix address pipe 0.
#define NRF_GZLL_DEFAULT_PREFIX_BYTE_1 2 ///< Default prefix address pipe 1.
#define NRF_GZLL_DEFAULT_PREFIX_BYTE_2 3 ///< Default prefix address pipe 2.
#define NRF_GZLL_DEFAULT_PREFIX_BYTE_3 4 ///< Default prefix address pipe 3.
#define NRF_GZLL_DEFAULT_PREFIX_BYTE_4 5 ///< Default prefix address pipe 4.
#define NRF_GZLL_DEFAULT_PREFIX_BYTE_5 6 ///< Default prefix address pipe 5.
#define NRF_GZLL_DEFAULT_PREFIX_BYTE_6 7 ///< Default prefix address pipe 6.
#define NRF_GZLL_DEFAULT_PREFIX_BYTE_7 8 ///< Default prefix address pipe 7.
#define NRF_GZLL_DEFAULT_BASE_ADDRESS_LENGTH NRF_GZLL_BASE_ADDRESS_LENGTH_4B ///< Default on-air base address length.
#define NRF_GZLL_DEFAULT_RX_PIPES_ENABLED 0x000000FF ///< Enabled Rx pipes. See nrf_gzll_set_rx_pipes_enabled().
/** @} */
/*****************************************************************************/
/** @name Default timeslot and synchronization configuration */
/*****************************************************************************/
#define NRF_GZLL_DEFAULT_TIMESLOT_PERIOD 600 ///< Default timeslot period.
#define NRF_GZLL_DEFAULT_TIMESLOTS_PER_CHANNEL 2 ///< Timeslots use by the Host and by the Device when communication is in sync.
#define NRF_GZLL_DEFAULT_DEVICE_CHANNEL_SELECTION_POLICY NRF_GZLL_DEVICE_CHANNEL_SELECTION_POLICY_USE_SUCCESSFUL ///< Default channel Gazell Device channel selection policy
#define NRF_GZLL_DEFAULT_MAX_TX_ATTEMPTS 0 ///< Default maximum TX attempts for each packet. A value of zero implies the infinite number of TX attempts.
#define NRF_GZLL_DEFAULT_XOSC_CTL NRF_GZLL_XOSC_CTL_AUTO ///< Deafult setting for controlling the XOSC
#define NRF_GZLL_DEFAULT_TIMESLOTS_PER_CHANNEL_WHEN_DEVICE_OUT_OF_SYNC 15 ///< Timeslots use by the Device before communication is in sync.
#define NRF_GZLL_DEFAULT_SYNC_LIFETIME (3 * NRF_GZLL_DEFAULT_CHANNEL_TABLE_SIZE * NRF_GZLL_DEFAULT_TIMESLOTS_PER_CHANNEL) ///< Number of timeslots to keep the timer running so that communication remains synchronized.
/** @} */
#define NRF_GZLL_PA_LNA_MAX_RAMP_UP_TIME 129 ///< Max external front end ramp up time [us].
#define NRF_GZLL_PA_LNA_PPI_CHANNELS_NUM 4 ///< Number of PPI channels used for front end control.
/** @} */
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,72 @@
/**
* Copyright (c) 2016 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* @file
* @brief Gazell error API.
*/
#ifndef NRF_GZLL_ERROR_H__
#define NRF_GZLL_ERROR_H__
#include "sdk_errors.h"
#include "nrf_gzll.h"
#include "app_error.h"
#ifdef __cplusplus
extern "C" {
#endif
#define GAZELLE_ERROR_CODE_CHECK(GZLL_RESULT) \
do \
{ \
if ((GZLL_RESULT) == false) \
{ \
nrf_gzll_error_code_t gzll_error_code = nrf_gzll_get_error_code(); \
ret_code_t error_code = gzll_error_code + NRF_ERROR_GAZELLE_ERR_BASE; \
APP_ERROR_HANDLER(error_code); \
} \
} while (0)
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,66 @@
/**
* Copyright (c) 2015 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef NRF_GZLL_RESOURCES_H__
#define NRF_GZLL_RESOURCES_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef GAZELL_ALTERNATIVE_RESOURCES
#define GZLL_PPI_CHANNELS_USED 0x00000007uL /**< PPI channels utilized by Gazell (not available to th spplication). */
#define GZLL_TIMERS_USED 0x00000004uL /**< Timers used by Gazell. */
#define GZLL_SWI_USED 0x00000001uL /**< Software interrupts used by Gazell */
#else
#define GZLL_PPI_CHANNELS_USED 0x00000700uL /**< PPI channels utilized by Gazell (not available to th spplication). */
#define GZLL_TIMERS_USED 0x00000001uL /**< Timers used by Gazell. */
#define GZLL_SWI_USED 0x00000002uL /**< Software interrupts used by Gazell */
#endif
#ifdef __cplusplus
}
#endif
#endif /* NRF_GZLL_RESOURCES_H__ */

View File

@@ -0,0 +1,363 @@
/**
* Copyright (c) 2009 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* @file
* @brief Implementation of Gazell Pairing Library (gzp), Common functions.
* @defgroup gzp_source_common Gazell Pairing common functions implementation
* @{
* @ingroup gzp_04_source
*/
#include "nrf_gzp.h"
#include "nrf_gzll.h"
#include "nrf_ecb.h"
#include <string.h>
#define SOURCE_FILE NRF_SOURCE_FILE_GZP ///< File identifer for asserts.
/******************************************************************************/
/** @name Global variables
* @{ */
/******************************************************************************/
/**
* Constant holding base address part of the pairing address.
*/
static const uint8_t pairing_base_address[4] = { GZP_ADDRESS };
/**
* Constant holding prefix byte of the pairing address.
*/
static const uint8_t pairing_address_prefix_byte = 0;
/**
* Constant holding pre-defined "validation ID".
*/
static const uint8_t gzp_validation_id[GZP_VALIDATION_ID_LENGTH] = GZP_VALIDATION_ID;
/**
* Constant holding pre-defined "secret key".
*/
static const uint8_t gzp_secret_key[16] = GZP_SECRET_KEY;
/**
* Variable used for AES key selection
*/
static gzp_key_select_t gzp_key_select;
/** @} */
/******************************************************************************/
/** @name Misc. external variables.
* @{ */
/******************************************************************************/
static uint8_t gzp_session_token[GZP_SESSION_TOKEN_LENGTH];
static uint8_t gzp_dyn_key[GZP_DYN_KEY_LENGTH];
/** @} */
/******************************************************************************/
/** @name Implementation common internal GZP functions
* @{ */
/******************************************************************************/
bool gzp_update_radio_params(const uint8_t* system_address)
{
uint8_t i;
uint8_t channels[NRF_GZLL_CONST_MAX_CHANNEL_TABLE_SIZE];
uint32_t channel_table_size;
uint32_t pairing_base_address_32, system_address_32;
bool update_ok = true;
bool gzll_enabled_state;
gzll_enabled_state = nrf_gzll_is_enabled();
// Configure "global" pairing address
pairing_base_address_32 = (pairing_base_address[0]) +
((uint32_t)pairing_base_address[1] << 8) +
((uint32_t)pairing_base_address[2] << 16) +
((uint32_t)pairing_base_address[3] << 24) ;
if (system_address != NULL)
{
system_address_32 = (system_address[0]) +
((uint32_t)system_address[1] << 8) +
((uint32_t)system_address[2] << 16) +
((uint32_t)system_address[3] << 24) ;
}
else
{
return false;
}
nrf_gzp_disable_gzll();
update_ok = update_ok && nrf_gzll_set_base_address_0(pairing_base_address_32);
update_ok = update_ok && nrf_gzll_set_address_prefix_byte(GZP_PAIRING_PIPE, pairing_address_prefix_byte);
update_ok = update_ok && nrf_gzll_set_base_address_1(system_address_32);
// Configure address for pipe 1 - 5. Address byte set to equal pipe number.
for (i = 1; i < NRF_GZLL_CONST_PIPE_COUNT; i++)
{
update_ok = update_ok && nrf_gzll_set_address_prefix_byte(i,i);
}
channel_table_size = nrf_gzll_get_channel_table_size();
gzp_generate_channels(&channels[0], system_address, channel_table_size);
// Write generated channel subset to Gazell Link Layer
update_ok = update_ok && nrf_gzll_set_channel_table(&channels[0], channel_table_size);
if (gzll_enabled_state)
{
update_ok = update_ok && nrf_gzll_enable();
}
return update_ok;
}
void gzp_generate_channels(uint8_t* ch_dst, const uint8_t* system_address, uint8_t channel_tab_size)
{
uint8_t binsize, spacing, i;
binsize = (GZP_CHANNEL_MAX - GZP_CHANNEL_MIN) / channel_tab_size;
ch_dst[0] = GZP_CHANNEL_LOW;
ch_dst[channel_tab_size - 1] = GZP_CHANNEL_HIGH;
if (system_address != NULL)
{
for (i = 1; i < (channel_tab_size - 1); i++)
{
ch_dst[i] = (binsize * i) + (system_address[i % 4] % binsize);
}
}
// If channels are too close, shift them to better positions
for (i = 1; i < channel_tab_size; i++)
{
spacing = (ch_dst[i] - ch_dst[i - 1]);
if (spacing < GZP_CHANNEL_SPACING_MIN)
{
ch_dst[i] += (GZP_CHANNEL_SPACING_MIN - spacing);
}
}
}
__INLINE void nrf_gzp_disable_gzll(void)
{
if (nrf_gzll_is_enabled())
{
nrf_gzll_disable();
__WFI();
while (nrf_gzll_is_enabled())
{
}
}
}
#ifndef GZP_CRYPT_DISABLE
void gzp_xor_cipher(uint8_t* dst, const uint8_t* src, const uint8_t* pad, uint8_t length)
{
uint8_t i;
for (i = 0; i < length; i++)
{
*dst = *src ^ *pad;
dst++;
src++;
pad++;
}
}
bool gzp_validate_id(const uint8_t* id)
{
return (memcmp(id, (void*)gzp_validation_id, GZP_VALIDATION_ID_LENGTH) == 0);
}
void gzp_add_validation_id(uint8_t* dst)
{
memcpy(dst, (void const*)gzp_validation_id, GZP_VALIDATION_ID_LENGTH);
}
void gzp_crypt_set_session_token(const uint8_t * token)
{
memcpy(gzp_session_token, (void const*)token, GZP_SESSION_TOKEN_LENGTH);
}
void gzp_crypt_set_dyn_key(const uint8_t* key)
{
memcpy(gzp_dyn_key, (void const*)key, GZP_DYN_KEY_LENGTH);
}
void gzp_crypt_get_session_token(uint8_t * dst_token)
{
memcpy(dst_token, (void const*)gzp_session_token, GZP_SESSION_TOKEN_LENGTH);
}
void gzp_crypt_get_dyn_key(uint8_t* dst_key)
{
memcpy(dst_key, (void const*)gzp_dyn_key, GZP_DYN_KEY_LENGTH);
}
void gzp_crypt_select_key(gzp_key_select_t key_select)
{
gzp_key_select = key_select;
}
void gzp_crypt(uint8_t* dst, const uint8_t* src, uint8_t length)
{
uint8_t i;
uint8_t key[16];
uint8_t iv[16];
// Build AES key based on "gzp_key_select"
switch (gzp_key_select)
{
case GZP_ID_EXCHANGE:
memcpy(key, (void const*)gzp_secret_key, 16);
break;
case GZP_KEY_EXCHANGE:
memcpy(key, (void const*)gzp_secret_key, 16);
gzp_get_host_id(key);
break;
case GZP_DATA_EXCHANGE:
memcpy(key, (void const*)gzp_secret_key, 16);
memcpy(key, (void const*)gzp_dyn_key, GZP_DYN_KEY_LENGTH);
break;
default:
return;
}
// Build init vector from "gzp_session_token"
for (i = 0; i < 16; i++)
{
if (i < GZP_SESSION_TOKEN_LENGTH)
{
iv[i] = gzp_session_token[i];
}
else
{
iv[i] = 0;
}
}
// Set up hal_aes using new key and init vector
(void)nrf_ecb_init();
nrf_ecb_set_key(key);
//hal_aes_setup(false, ECB, key, NULL); // Note, here we skip the IV as we use ECB mode
// Encrypt IV using ECB mode
(void)nrf_ecb_crypt(iv, iv);
// Encrypt data by XOR'ing with AES output
gzp_xor_cipher(dst, src, iv, length);
}
void gzp_random_numbers_generate(uint8_t * dst, uint8_t n)
{
uint8_t i;
NRF_RNG->EVENTS_VALRDY=0;
NRF_RNG->TASKS_START = 1;
for (i = 0; i < n; i++)
{
while (NRF_RNG->EVENTS_VALRDY==0)
{}
dst[i] = (uint8_t)NRF_RNG->VALUE;
NRF_RNG->EVENTS_VALRDY=0;
}
NRF_RNG->TASKS_STOP = 1;
}
/******************************************************************************/
/** @name Implementation of nRF51 specific GZP functions
* @{ */
/******************************************************************************/
/**
* @brief Function for setting the Primask variable. Only necessary if ARMCC
* compiler skips __set_PRIMASK at high optimization levels.
*
* @param primask The primask value. 1 to disable interrupts, 0 otherwise.
*/
static void nrf_gzp_set_primask(uint32_t primask)
{
#if defined(__CC_ARM)
//lint -save -e10 -e618 -e438 -e550 -e526 -e628 -e526
volatile register uint32_t __regPriMask __ASM("primask");
__regPriMask = (primask);
#else
__set_PRIMASK(primask);
#endif
//lint -restore
}
void nrf_gzp_flush_rx_fifo(uint32_t pipe)
{
static uint8_t dummy_packet[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH];
uint32_t length;
nrf_gzp_set_primask(1);
while (nrf_gzll_get_rx_fifo_packet_count(pipe) >0)
{
length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH;
(void)nrf_gzll_fetch_packet_from_rx_fifo(pipe,dummy_packet,&length);
}
nrf_gzp_set_primask(0);
}
/** @} */
/******************************************************************************/
/** @name Implementation of debug functions
* @{ */
/******************************************************************************/
/** @} */
/** @} */
#endif

View File

@@ -0,0 +1,665 @@
/**
* Copyright (c) 2012 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* @file
* @brief Gazell Pairing API
*/
#ifndef __GZP_H
#define __GZP_H
#include "nrf.h"
#include "nrf_gzp_config.h"
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @defgroup gzp_02_api Gazell Pairing
* @{
* @ingroup modules_02_gzp
* @brief Gazell Pairing Application Programming Interface (API).
*/
/******************************************************************************/
/** @name Pairing configuration defines
* @{ */
/******************************************************************************/
#define GZP_PAIRING_PIPE 0 ///< Pipe reserved for initial pairing communication.
#define GZP_DATA_PIPE 1 ///< Pipe reserved for GZP encrypted data communication (one pipe only).
#define GZP_TX_RX_TRANS_DELAY 10 ///< Time to wait between request and fetch packets in RX_PERIODS (2 timeslot periods)
#define GZP_SYSTEM_ADDRESS_WIDTH 4 ///< Must equal Gazell base address length.
#define GZP_VALIDATION_ID {0x32, 0x53, 0x66} ///< Validation ID. Required to be shared by Host and Device. Not a secret.
#define GZP_VALIDATION_ID_LENGTH 3 ///< Validation ID length in bytes.
#define GZP_HOST_ID_LENGTH 5 ///< Host ID length in bytes.
#define GZP_SESSION_TOKEN_LENGTH GZP_HOST_ID_LENGTH ///< Session token length in bytes.
#define GZP_DYN_KEY_LENGTH (16 - GZP_VALIDATION_ID_LENGTH) ///< Dynamic key length in bytes.
#define GZP_HOST_RX_POWER_THRESHOLD -64 ///< RSSI threshold for when signal strength in RX packet power is high enough.
/** @} */
/******************************************************************************/
/** @name Device -> Host packet definitions
* @{ */
/******************************************************************************/
#define GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH 1 ///< "Host address request" packet, payload length
#define GZP_CMD_HOST_ADDRESS_FETCH_PAYLOAD_LENGTH 1 ///< "Host address fetch" packet, payload length
#define GZP_CMD_HOST_ID_REQ_SESSION_TOKEN 1 ///< "Host ID request" packet, session token position
#define GZP_CMD_HOST_ID_REQ_PAYLOAD_LENGTH (GZP_CMD_HOST_ID_REQ_SESSION_TOKEN + GZP_SESSION_TOKEN_LENGTH) ///< "Host ID request" payload length
#if (GZP_CMD_HOST_ID_REQ_PAYLOAD_LENGTH > 17)
#error GZP_SESSION_TOKEN_LENGTH too long.
#endif
#define GZP_CMD_HOST_ID_FETCH_VALIDATION_ID 1 ///< "Host ID fetch" packet
#define GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH (GZP_CMD_HOST_ID_FETCH_VALIDATION_ID + GZP_VALIDATION_ID_LENGTH) ///< "Host ID fetch" payload length
#if (GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH > 17)
#error GZP_VALIDATION_ID_LENGTH set too long.
#endif
#define GZP_CMD_KEY_UPDATE_PREPARE_PAYLOAD_LENGTH 1 ///< "Key update prepare" payload length
#define GZP_CMD_KEY_UPDATE_VALIDATION_ID 1 ///< "Key update" packet, validation ID position
#define GZP_CMD_KEY_UPDATE_NEW_KEY (GZP_CMD_KEY_UPDATE_VALIDATION_ID + GZP_VALIDATION_ID_LENGTH) ///< "Key update" packet, new key position
#define GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH (GZP_CMD_KEY_UPDATE_NEW_KEY + GZP_DYN_KEY_LENGTH) ///< "Key update" packet, payload length
#if (GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH > 17)
#error Sum (GZP_VALIDATION_ID_LENGTH + GZP_DYN_KEY_LENGTH) too high.
#endif
#define GZP_CMD_ENCRYPTED_USER_DATA_VALIDATION_ID 1 ///< "Encrypted user data" packet, validation ID position
#define GZP_CMD_ENCRYPTED_USER_DATA_PAYLOAD ((GZP_CMD_ENCRYPTED_USER_DATA_VALIDATION_ID + GZP_VALIDATION_ID_LENGTH)) ///< "Encrypted user data" packet, user data position
#define GZP_ENCRYPTED_USER_DATA_PACKET_OVERHEAD ( GZP_CMD_ENCRYPTED_USER_DATA_VALIDATION_ID + GZP_VALIDATION_ID_LENGTH) ///< "Encrypted user data" packet, packet overhead length
#define GZP_ENCRYPTED_USER_DATA_MAX_LENGTH (17 - GZP_ENCRYPTED_USER_DATA_PACKET_OVERHEAD) ///< "Encrypted user data" packet, max payload length
#if (GZP_MAX_FW_PAYLOAD_LENGTH < 17)
#error GZP_MAX_FW_PAYLOAD_LENGTH must be greater or equal to 17.
#endif
#define GZP_CMD_FETCH_RESP_PAYLOAD_LENGTH 1 ///< General "fetch response" packet, payload_length
/** @} */
/******************************************************************************/
/** @name Host -> Device packet definitions
* @{ */
/******************************************************************************/
#define GZP_CMD_HOST_ADDRESS_RESP_ADDRESS 1 ///< "Host address fetch" response packet, address position
#define GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH (GZP_CMD_HOST_ADDRESS_RESP_ADDRESS + GZP_SYSTEM_ADDRESS_WIDTH) ///< ///< "Host address fetch" response packet, payload length
#if (GZP_MAX_ACK_PAYLOAD_LENGTH < GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH)
#error GZP_MAX_ACK_PAYLOAD_LENGTH must be greater or equal to GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH.
#endif
#define GZP_CMD_HOST_ID_FETCH_RESP_VALIDATION_ID 1 ///< "Host ID fetch" response packet, validation ID position
#define GZP_CMD_HOST_ID_FETCH_RESP_STATUS (GZP_CMD_HOST_ID_FETCH_RESP_VALIDATION_ID + GZP_VALIDATION_ID_LENGTH) ///< "Host ID fetch" response packet, status position
#define GZP_CMD_HOST_ID_FETCH_RESP_HOST_ID (GZP_CMD_HOST_ID_FETCH_RESP_STATUS + 1) ///< "Host ID fetch" response packet, Host ID position
#define GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH (GZP_CMD_HOST_ID_FETCH_RESP_HOST_ID + GZP_HOST_ID_LENGTH) ///< "Host ID fetch" response packet, payload length
#if (GZP_MAX_ACK_PAYLOAD_LENGTH < GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH)
#error GZP_MAX_ACK_PAYLOAD_LENGTH must be greater or equal to GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH.
#endif
#define GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN 1 ///< "Key update prepare" response packet, session token position
#define GZP_CMD_KEY_UPDATE_PREPARE_RESP_PAYLOAD_LENGTH (GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN + GZP_SESSION_TOKEN_LENGTH) ///< "Key update prepare" response packet, payload length position
#if (GZP_MAX_ACK_PAYLOAD_LENGTH < GZP_CMD_KEY_UPDATE_PREPARE_RESP_PAYLOAD_LENGTH)
#error GZP_MAX_ACK_PAYLOAD_LENGTH must be greater or equal to GZP_CMD_KEY_UPDATE_PREPARE_RESP_PAYLOAD_LENGTH.
#endif
#define GZP_CMD_ENCRYPTED_USER_DATA_RESP_SESSION_TOKEN 1 ///< "Encrypted user data" response packet, session token position
#define GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID (GZP_CMD_ENCRYPTED_USER_DATA_RESP_SESSION_TOKEN + GZP_SESSION_TOKEN_LENGTH) ///< "Encrypted user data" response packet, validation ID position
#define GZP_CMD_ENCRYPTED_USER_DATA_RESP_PAYLOAD_LENGTH (GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID + GZP_VALIDATION_ID_LENGTH) ///< "Encrypted user data" response packet, payload length position
#if (GZP_MAX_ACK_PAYLOAD_LENGTH < GZP_CMD_ENCRYPTED_USER_DATA_RESP_PAYLOAD_LENGTH)
#error GZP_MAX_ACK_PAYLOAD_LENGTH must be greater or equal to GZP_CMD_ENCRYPTED_USER_DATA_RESP_PAYLOAD_LENGTH.
#endif
#if (GZP_VALIDATION_ID_LENGTH > GZP_HOST_ID_LENGTH)
#error GZP_HOST_ID_LENGTH should be greater or equal to GZP_VALIDATION_ID_LENGTH.
#endif
#if (GZP_SESSION_TOKEN_LENGTH != GZP_HOST_ID_LENGTH)
#error GZP_SESSION_TOKEN_LENGTH must equal GZP_HOST_ID_LENGTH.
#endif
#ifdef GZLL_CRYPT_ENABLE
#error Gazell encryption can not be enabled when using the Gazell pairing library. \
GZLL_CRYPT_ENABLE must be undefined.
#endif
/** @} */
/******************************************************************************/
/** @name Typedefs
* @{ */
/******************************************************************************/
/**
* @enum gzp_key_select_t
* @brief Enumerator used for selecting the key to be used for encryption.
*/
typedef enum
{
GZP_ID_EXCHANGE, ///< "Secret key" only
GZP_KEY_EXCHANGE, ///< "Secret key" and "Host ID"
GZP_DATA_EXCHANGE ///< "Dynamic key" and "Host ID"
} gzp_key_select_t;
/**
* @enum gzp_cmd_t
* @brief Enumerator used in the first payload byte of each packet to
* indicate the packet type.
*/
typedef enum
{
GZP_CMD_HOST_ADDRESS_REQ = 0, ///< Host address request
GZP_CMD_HOST_ADDRESS_FETCH, ///< Host address fetch
GZP_CMD_HOST_ID_REQ, ///< Host ID request
GZP_CMD_HOST_ID_FETCH, ///< Host ID fetch request
GZP_CMD_KEY_UPDATE_PREPARE, ///< Key update prepare
GZP_CMD_KEY_UPDATE, ///< Key update
GZP_CMD_ENCRYPTED_USER_DATA, ///< Encrypted user data
GZP_CMD_FETCH_RESP, ///< Fetch response
GZP_CMD_HOST_ADDRESS_RESP, ///< Host address response
GZP_CMD_HOST_ID_FETCH_RESP, ///< Host ID fetch response
GZP_CMD_KEY_UPDATE_PREPARE_RESP, ///< Key update prepare
GZP_CMD_ENCRYPTED_USER_DATA_RESP, ///< Encrypted user data response
} gzp_cmd_t;
/**
* @enum gzp_id_req_res_t
* @brief Enumerator used to identify the state of the current
* Host ID request.
*/
typedef enum
{
GZP_ID_RESP_PENDING, ///< ID response pending
GZP_ID_RESP_GRANTED, ///< ID response granted
GZP_ID_RESP_REJECTED, ///< ID response rejected
GZP_ID_RESP_FAILED, ///< ID response failed
GZP_ID_RESP_NO_REQUEST ///< Default value. No ID request has yet been received.
} gzp_id_req_res_t;
/** @} */
/******************************************************************************/
/** @name Misc. function prototypes
* @{ */
/******************************************************************************/
/**
* Set the session token.
*
* @param token Pointer to the session token to set.
*/
void gzp_crypt_set_session_token(const uint8_t *token);
/**
* Get the session token.
*
* @param dst_token Pointer to write the session token.
*/
void gzp_crypt_get_session_token(uint8_t *dst_token);
/**
* Set the dynamic key.
*
* @param dyn_key Pointer to the dynamic key to set.
*/
void gzp_crypt_set_dyn_key(const uint8_t* dyn_key);
/**
* Get the dynamic key.
*
* @param dst_key Pointer to write the dynamic key too.
*/
void gzp_crypt_get_dyn_key(uint8_t *dst_key);
/**
* Set the Host ID.
*
* @param src Pointer to the Host ID to set.
*/
static void gzp_set_host_id(const uint8_t* src);
/**
* Get the Host ID.
*
* @param dst Pointer to write the Host ID to.
*/
void gzp_get_host_id(uint8_t *dst);
/**
* Selecting what key-set that should be used when encrypting data
* using gzp_crypt().
*
* @param key_select Key-set to use.
*/
void gzp_crypt_select_key(gzp_key_select_t key_select);
/**
* Encypt / decrypt data.
*
* The current "session token" will be used as initialization vector (IV).
* The AES key to be used is selected by gzp_crypt_select_key().
* AES is a symmetric encryption scheme, this function can be used
* to perform both encryption and decryption.
*
* @param dst Destination to write encrypted data to. Should be 16 bytes long.
* @param src Source data to encrypt.
* @param length Length in bytes of src.
*/
void gzp_crypt(uint8_t* dst, const uint8_t* src, uint8_t length);
/**
* Compare the *src_id with a pre-defined validation ID.
*
* @param src_id Pointer to the source validation ID to compare to.
*
* @retval true If *src_id equals the pre-defined ID.
* @retval false If *src_id does not equal the pre-defined ID.
*/
bool gzp_validate_id(const uint8_t *src_id);
/**
* Add the pre-defined validation ID to dst_id.
* GZP_VALIDATION_ID_LENGTH bytes will be added.
*
* @param dst_id Pointer to add the GZP validation ID to.
*/
void gzp_add_validation_id(uint8_t *dst_id);
/**
* Generate random bytes.
*
* @param dst Destination to write the random bytes to.
* @param n Number of bytes to generate.
*/
void gzp_random_numbers_generate(uint8_t *dst, uint8_t n);
/**
* Update the channel table and the system address.
*
* The channel table is updated to pseudo-random set generated using the
* system address. The channel table still includes GZP_CHANNEL_MAX and
* GZP_CHANNEL_MIN.
* The system address is applied to base address 1 and therefore applies
* to pipes 1-7.
*
* @param system_address Pointer to the system_address to set.
*
* @retval true If theradio parameters were updated successfully.
* @retval false If there was an error updated the radio parameters.
*/
bool gzp_update_radio_params(const uint8_t *system_address);
/**
* Generate a set of channels from a 4 byte address.
*
* @param ch_dst Destination to write the channel set to. The channel set
* includes GZP_CHANNEL_MAX and GZP_CHANNEL_MIN.
* @param address Four byte address to generate the channel set from.
* @param channel_set_size Size of the channel set to generate.
*/
void gzp_generate_channels(uint8_t *ch_dst, const uint8_t * address, uint8_t channel_set_size);
/**
* Perform an XOR on two byte strings.
*
* @param dst Destination to write the result to. Should be of size length.
* @param src
* @param pad
* @param length Number of bytes to perform the XOR operation on.
*/
void gzp_xor_cipher(uint8_t* dst, const uint8_t* src, const uint8_t* pad, uint8_t length);
/******************************************************************************/
/** @name Common Device and Host functions
* @{ */
/******************************************************************************/
/**
* Initialization function. This function initializes the Gazell Pairing Library.
* This function must be called before any of the other Gazell Pairing Library functions are
* used and must be called @b after gzll_init() is called.
*
*/
void gzp_init(void);
/**
* Function for erasing all pairing data.
*/
void gzp_erase_pairing_data(void);
/**
* Disable Gazell and sleep while waiting for nrf_gzll_disabled callback.
*/
void nrf_gzp_disable_gzll(void);
/**
Function for cancelling an ongoing (pending) "Host ID request".
After calling this function the "Host ID request" status will go to
"ID request Idle".
*/
void gzp_id_req_cancel(void);
/**
* Flush the GZLL RX FIFO for a specific pipe while GZLL is disabled.
*
* @param pipe Pipe.
*/
void nrf_gzp_flush_rx_fifo(uint32_t pipe);
/**
@name Device functions
*/
/**
* Check whether current GZP packet transaction has completed.
*
* @retval true
* @retval false
*/
bool nrf_gzp_tx_complete(void);
/**
* Check whether previous GZP packet transaction was successful.
*
* @retval true
* @retval false
*/
bool nrf_gzp_tx_success(void);
/**
* Reset tx_complete status.
*/
void nrf_gzp_reset_tx_complete(void);
/**
* Reset tx_success status.
*/
void nrf_gzp_reset_tx_success(void);
/**
* Function to check whether a Device has existing pairing data, implying that it is
* paired to a Host.
*
* @retval -2 The pairing database is empty.
* @retval -1 The device has a system address but no Host ID.
* @retval >=0 The device has a system address and HostID at this index value in the database.
*/
int8_t gzp_get_pairing_status(void);
/**
Function for sending a "system address" request to a Host.
When calling this function the Device will attempt acquiring the "system address" from
any Host within close proximity.
If a host is located within close proximity and pairing is enabled in the Host,
a "system address" will be sent in return to the Device.
The new "system address" will apply immediately in the Device, and the new "system address"
will be stored in non volatile (NV) memory.
Note. Using OTP devices limits the number of times a new "system address" can
be stored in NV memory.
@return
@retval true if new "system address" was received from a Host.
@retval false if no "system address" was received from a Host.
*/
bool gzp_address_req_send(void);
/**
Function for sending a "Host ID request" to a Host.
The "Host ID" is needed to be able to send encrypted data using
gzp_crypt_data_send().
The request will be sent using the "system address" previously received using
gzp_address_req_send().
It is not required that the Host is within close proximity in order to acquire the
"Host ID".
The new "Host ID" will apply immediately for the Device, and the new "Host ID"
will be stored in non volatile (NV) memory.
Note. Using OTP devices limits the number of times a new "Host ID" can
be stored in NV memory.
@return
@retval GZP_ID_RESP_PENDING if a "Host ID request" has been sent to the Host, but the Host application has
not yet decided whether to Grant or Reject the "ID request".
@retval GZP_ID_RESP_GRANTED if the "Host ID" has been received from the Host. The received "Host ID" will be stored
in non volatile memory.
@retval GZP_ID_RESP_REJECTED if the Host application has rejected the "Host ID request".
@retval GZP_ID_RESP_FAILED if failing to send a request or receive a response from the Host.
*/
gzp_id_req_res_t gzp_id_req_send(void);
/**
Function for sending encrypted user data to the Host.
Before any data can be sent the Device must acquire both the Host's
"system address" by using gzp_address_req_send() and the "Host ID" by using
gzp_id_req_send().
@param *src is a pointer to the data packet to be sent.
@param length is the length of the data packet to be sent.
@return
@retval true if the data was successfully transmitted and decrypted by the Host.
@retval false if data transmission failed or Host failed to decryption data correctly.
*/
bool gzp_crypt_data_send(const uint8_t *src, uint8_t length);
/**
@name Host functions
*/
/**
Function for enabling/disabling pairing in a host. When pairing is enabled the host will
be monitoring for "system address" and "Host ID" requests from Devices.
A "system address request" received from a Device will always be granted.
When a "host ID request" has been received, the Host application have to grant,
reject or cancel this by using one of the following functions:
- gzp_id_req_grant()
- gzp_id_req_reject()
- gzp_id_req_cancel()
@param enable
@arg true enables pairing.
@arg false disables pairing.
*/
void gzp_pairing_enable(bool enable);
/**
* Execute the Gazell Pairing Library Host operation.
*
* This function must be called regularly by the Host application.
*/
void gzp_host_execute(void);
/**
* Address exchanged check.
*
* @retval true If a "system address" was delivered to a requesting Device during the
* previous call to gzp_host_execute();
* @retval false Otherwise.
*/
bool gzp_address_exchanged(void);
/**
Function for checking if a "Host ID request" has been received from a Device.
If a request has been received, the Pairing library will enter "ID request pending"
state.
The application is responsible for responding to this request by calling
one of the following functions:
- gzp_id_req_grant()
- gzp_id_req_reject()
- gzp_id_req_cancel()
@retval true if a "Host ID request" has been received (internal state is "ID request pending")
@retval false if no "Host ID request" has been received (internal state is "ID request idle")
*/
bool gzp_id_req_received(void);
/**
Function for rejecting the previously received "Host ID request". This function should be called
only when a "Host ID request" has been received (internal state is "ID request pending").
The internal state of the Pairing library will remain "ID request pending" until the a "reject" message
has been successfully transmitted to the requesting Device. After this the internal state will
change to "ID request idle".
*/
void gzp_id_req_reject(void);
/**
* Function for granting the previously received "Host ID request". This function should be called
only when a "Host ID request" has been received (internal state is "ID request pending").
The internal state of the Pairing library will remain "ID request pending" until the "Host ID" has
been successfully transmitted to the requesting Device. After this the internal state will
change to "ID request idle".
*/
void gzp_id_req_grant(void);
/**
* Check if user data has been received.
*
* @retval true If encrypted user data has been received.
* @retval false Otherwise.
*/
bool gzp_crypt_user_data_received(void);
/**
Function for reading encrypted user data.
Note that the read user data will be automatically decrypted. Only data
that was decrypted correctly will be presented.
@param dst* is a pointer to where the received data will be written.
@param length* is a pointer for returning the number of bytes received. Only 1 byte will
be writtem to length*.
@return
@retval true if data has been received and is written to dst*
@retval false if no data has been received.
*/
bool gzp_crypt_user_data_read(uint8_t* dst, uint8_t* length);
/**
Function emulating behavior of gzll_rx_start() in legeacy nRF24xx Gaell
linbrary.
This functions sets Gazell in Host mode and starts reception (enable).
*/
void gzll_rx_start(void);
/** @} */
/** @} */
/** @} */
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,823 @@
/**
* Copyright (c) 2009 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
/**
* @file
* @brief Implementation of Gazell Pairing Library (gzp), Host functions.
* @defgroup gzp_source_host Gazell Pairing Host implementation
* @{
* @ingroup gzp_04_source
*/
#include "nrf_gzp.h"
#include "nrf_gzll.h"
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "nrf_assert.h"
#include "nrf_ecb.h"
#include "nrf_nvmc.h"
//lint -esym(40, GZP_PARAMS_STORAGE_ADR) "Undeclared identifier"
#define GZP_PARAMS_DB_ADR GZP_PARAMS_STORAGE_ADR // Address of the GZP parameters flash page.
/******************************************************************************/
/** @name Typedefs
* @{ */
/******************************************************************************/
/**
* Definition of internal states.
*/
typedef enum
{
GZP_ID_REQ_IDLE, ///< No Host ID request received from Device.
GZP_ID_REQ_PENDING, ///< Host ID request received and waiting on application to grant/reject.
GZP_ID_REQ_PENDING_AND_GRANTED, ///< Host ID request received and granted by application.
GZP_ID_REQ_PENDING_AND_REJECTED, ///< Host ID request received and rejected by application.
} gzp_id_req_stat_t;
/** @} */
/******************************************************************************/
/** @name Internal (static) function prototypes
* @{ */
/******************************************************************************/
/**
* Function for incrementing internal session counter.
*/
static void gzp_session_counter_inc(void);
/**
* Function for reading value of internal session counter.
* @param dst Current session counter.
*/
static void gzp_get_session_counter(uint8_t* dst);
/**
* Function processing received "system address request" from Device.
*
* @param gzp_req Pointer to RX payload containing system address request.
*/
static void gzp_process_address_req(uint8_t* gzp_req);
/**
* Function to process Host ID request from device.
*
* The Host shall retrieve the Host ID from NVM, or shall generate if
* it does not yet exist.
*
* @param rx_payload Pointer to rx_payload contaning Host ID request.
*/
static void gzp_process_id_req(uint8_t* rx_payload);
/**
* Function to process Host ID fetch request from Device.
*
* The Device fetches the Host ID after the Host has generated/retrieved
* the Host ID.
*
* @param rx_payload Pointer to rx_payload contaning Host ID fetch request.
*/
static void gzp_process_id_fetch(uint8_t* rx_payload);
/**
* Function to process Key Update Prepare packet.
*
* Device requests the Session Token to be used for the Key Update request.
*/
static void gzp_process_key_update_prepare(void);
/**
* Function to process Key Update packet.
*
* Device requests a Key Update and sends a new Dynamic Key. The Dynamic Key is
* updated on the Host.
*
* @param rx_payload Pointer to rx_payload containing Key Update request.
*/
static void gzp_process_key_update(uint8_t* rx_payload);
/**
* Function to process received Encrypted User packet.
*
* @param rx_payload Pointer to rx_payload containing the encrypted user data.
* @param length Length of encrypted user data.
*/
static void gzp_process_encrypted_user_data(uint8_t* rx_payload, uint8_t length);
/**
* Function to preload the payload for the next ACK.
*
* @param src Pointer to source payload.
* @param length Length of source payload.
* @param pipe Pipe for the ACK payload.
*/
static void gzp_preload_ack(uint8_t* src, uint8_t length, uint8_t pipe);
/**
* Function for reading the Chip ID from non-volatile memory.
*
* The chip ID is used for the system address.
*
* If the Chip ID is not yet created a random Chip ID is created and
* written to non-volatile memory. Note that the term chip ID is used as
* the factory programmed chip sequence number was used for the system
* address in nRF24LU ICs.
*
* @param dst Address to copy Host ID to.
* @param[in] n Number of bytes in the Host ID.
*/
void gzp_host_chip_id_read(uint8_t *dst, uint8_t n);
/**
* Function to set the Host ID.
*
* Writes the Host ID to non-volatile memory.
* @param src Address of the Host ID to copy from.
*/
static void gzp_set_host_id(const uint8_t* src);
/**
* Function to request disabling of Gazell and wait for it to be disabled.
*
* Emulates legacy gzll_goto_idle().
*/
static void gzll_goto_idle(void);
/**
* Flush all TX FIFOs.
*
* Emulates legacy gzll_tx_fifo_flush().
*/
static void gzll_tx_fifo_flush(void);
/**
* Flush all RX FIFOs.
*
* Emulates legacy gzll_rx_fifo_flush().
*/
static void gzll_rx_fifo_flush(void);
/**
* Set a timeout for the reception of packets on the Gazell Host.
*
* Emulates legacy Gazell function: gzll_set_param(GZLL_PARAM_RX_TIMEOUT, x).
*
* @param timeout Timeout in number of legacy "RX periods"
* (1 RX period = 2 timeslot periods).
*/
static void gzll_set_rx_timeout(uint32_t timeout);
/** @} */
/******************************************************************************/
/** @name Internal (static) variabls
* @{ */
/******************************************************************************/
static gzp_id_req_stat_t gzp_id_req_stat; ///< Current state of Host ID request.
static bool gzp_pairing_enabled_f; ///< True if Host is paired with a device.
static bool gzp_address_exchanged_f; ///< True if Host has exchanged a system address with a device and thus pairing has begun.
static uint8_t gzp_session_counter[GZP_SESSION_TOKEN_LENGTH]; ///< Session counter used for key generation and update.
static bool gzp_encrypted_user_data[GZP_ENCRYPTED_USER_DATA_MAX_LENGTH]; ///< Placeholder for encrypted data from Device.
static uint8_t gzp_encrypted_user_data_length; ///< Length of gzp_encrypted_user_data. Zero implies no data received.
static nrf_gzll_host_rx_info_t prev_gzp_rx_info = {0, 0}; ///< RSSI and status of ACK payload transmission of previous Gazell packet.
// Define Macro to make array initialization nicer
#define REP4(X) X X X X
#if defined(__ICCARM__)
#if GZP_PARAMS_DB_ADR == 0x1000
static const uint32_t database[GZP_DEVICE_PARAMS_STORAGE_SIZE/4] @ "gzp_dev_data"
#elif GZP_PARAMS_DB_ADR == 0x15000
static const uint32_t database[GZP_DEVICE_PARAMS_STORAGE_SIZE/4] @ "gzp_dev_data_sd"
#else
#error
#endif
#elif defined(__GNUC__)
static const uint32_t database[GZP_DEVICE_PARAMS_STORAGE_SIZE / 4] __attribute__((section(".gzll_paring")))
#else
static const uint32_t database[GZP_DEVICE_PARAMS_STORAGE_SIZE / 4] __attribute__((at(GZP_PARAMS_DB_ADR)))
#endif
= {
#define STATIC_INIT_VALUE 0xFFFFFFFF
#define STATIC_INIT_COUNT (GZP_DEVICE_PARAMS_STORAGE_SIZE / 4)
#define INIT_1 STATIC_INIT_VALUE,
#define INIT_4 REP4(INIT_1)
#define INIT_16 REP4(INIT_4)
#define INIT_64 REP4(INIT_16)
#define INIT_256 REP4(INIT_64)
#define INIT_1024 REP4(INIT_256)
#if (STATIC_INIT_COUNT == 256)
INIT_256
#elif (STATIC_INIT_COUNT == 1024)
INIT_1024
#else
#error Gazell Pairing Library database not initialized properly!
#endif
}; ///< Database for storing keys.
/** @} */
/******************************************************************************/
// Implementation: Host-specific API functions
/******************************************************************************/
void gzp_init()
{
uint8_t system_address[GZP_SYSTEM_ADDRESS_WIDTH];
// Read "chip id", of which 4 bytes (GZP_SYSTEM_ADDRESS_WIDTH)
// are used as system address
gzp_host_chip_id_read(system_address, GZP_SYSTEM_ADDRESS_WIDTH);
// Set up radio parameters (addresses and channel subset) from system_address
(void)gzp_update_radio_params(system_address);
// Only "data pipe" enabled by default
(void)nrf_gzll_set_rx_pipes_enabled(nrf_gzll_get_rx_pipes_enabled() | (1 << GZP_DATA_PIPE));
gzp_pairing_enabled_f = false;
gzp_address_exchanged_f = false;
gzp_id_req_stat = GZP_ID_REQ_IDLE;
gzp_encrypted_user_data_length = 0;
// Infinite RX timeout
gzll_set_rx_timeout(0);
}
void gzp_pairing_enable(bool enable)
{
if (gzp_pairing_enabled_f != enable)
{
gzll_goto_idle();
if (enable)
{
(void)nrf_gzll_set_rx_pipes_enabled(nrf_gzll_get_rx_pipes_enabled() | (1 << GZP_PAIRING_PIPE));
}
else
{
(void)nrf_gzll_set_rx_pipes_enabled(nrf_gzll_get_rx_pipes_enabled() & ~(1 << GZP_PAIRING_PIPE));
gzp_id_req_stat = GZP_ID_REQ_IDLE;
}
gzp_pairing_enabled_f = enable;
gzll_rx_start();
}
}
void gzp_host_execute()
{
bool gzp_packet_received = false;
uint32_t payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH;
uint8_t rx_payload[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH];
gzp_address_exchanged_f = false;
if (nrf_gzll_get_rx_fifo_packet_count(GZP_PAIRING_PIPE) > 0)
{
gzp_packet_received = nrf_gzll_fetch_packet_from_rx_fifo(GZP_PAIRING_PIPE, rx_payload, &payload_length);
}
if (!gzp_packet_received && (gzp_encrypted_user_data_length == 0))
{
if (nrf_gzll_get_rx_fifo_packet_count(GZP_DATA_PIPE) > 0)
{
gzp_packet_received = nrf_gzll_fetch_packet_from_rx_fifo(GZP_DATA_PIPE, rx_payload, &payload_length);
}
}
if (gzp_packet_received)
{
//lint -save -esym(644,rx_payload) //may not have been initialized
switch (rx_payload[0])
{
case GZP_CMD_HOST_ADDRESS_REQ:
gzp_process_address_req(rx_payload);
break;
#ifndef GZP_CRYPT_DISABLE
case GZP_CMD_HOST_ID_REQ:
gzp_process_id_req(rx_payload);
break;
case GZP_CMD_HOST_ID_FETCH:
gzp_process_id_fetch(rx_payload);
break;
case GZP_CMD_KEY_UPDATE_PREPARE:
gzp_process_key_update_prepare();
break;
case GZP_CMD_KEY_UPDATE:
gzp_process_key_update(rx_payload);
break;
case GZP_CMD_ENCRYPTED_USER_DATA:
gzp_process_encrypted_user_data(rx_payload, payload_length);
break;
#endif
case GZP_CMD_FETCH_RESP:
default:
break;
}
}
// Restart reception if "not proximity backoff" period has elapsed
if (!nrf_gzll_is_enabled())
{
gzll_set_rx_timeout(0);
if (gzp_pairing_enabled_f)
{
(void)nrf_gzll_set_rx_pipes_enabled(nrf_gzll_get_rx_pipes_enabled() | (1 << GZP_PAIRING_PIPE));
}
gzll_rx_start();
}
#ifndef GZP_CRYPT_DISABLE
gzp_session_counter_inc();
#endif
}
void gzll_rx_start(void)
{
if (nrf_gzll_get_mode() != NRF_GZLL_MODE_HOST)
{
gzll_goto_idle();
(void)nrf_gzll_set_mode(NRF_GZLL_MODE_HOST);
}
if (!nrf_gzll_is_enabled())
{
(void)nrf_gzll_enable();
}
}
bool gzp_id_req_received()
{
return (gzp_id_req_stat != GZP_ID_REQ_IDLE);
}
void gzp_id_req_reject()
{
if (gzp_id_req_received())
{
gzp_id_req_stat = GZP_ID_REQ_PENDING_AND_REJECTED;
}
}
void gzp_id_req_grant()
{
if (gzp_id_req_received())
{
gzp_id_req_stat = GZP_ID_REQ_PENDING_AND_GRANTED;
}
}
void gzp_id_req_cancel()
{
if (gzp_id_req_received())
{
gzp_id_req_stat = GZP_ID_REQ_IDLE;
}
}
//-----------------------------------------------------------------------------
// Implementation: Static functions
//-----------------------------------------------------------------------------
static void gzp_process_address_req(uint8_t* gzp_req)
{
uint8_t temp_rx_pipes;
uint8_t pairing_resp[GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH];
uint32_t rx_payload_length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH;
gzp_address_exchanged_f = false;
gzll_goto_idle();
ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
temp_rx_pipes = nrf_gzll_get_rx_pipes_enabled();
ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
// If requesting Device within close proximity
if (prev_gzp_rx_info.rssi >= GZP_HOST_RX_POWER_THRESHOLD)
{
(void)nrf_gzll_set_rx_pipes_enabled(0);
ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
gzll_set_rx_timeout(GZP_CLOSE_PROXIMITY_BACKOFF_RX_TIMEOUT);
ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
gzll_rx_fifo_flush();
ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
// Start "proximity" back off period
gzll_rx_start();
ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
while (nrf_gzll_is_enabled())
{}
// Build pairing response packet
pairing_resp[0] = (uint8_t)GZP_CMD_HOST_ADDRESS_RESP;
gzp_host_chip_id_read(&pairing_resp[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH);
(void)nrf_gzll_add_packet_to_tx_fifo(0, &pairing_resp[0], GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH);
ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
gzll_set_rx_timeout(GZP_STEP1_RX_TIMEOUT);
// Enable only pairing pipe when waiting for pairing request step 1
(void)nrf_gzll_set_rx_pipes_enabled((1 << GZP_PAIRING_PIPE));
gzll_rx_start();
while (nrf_gzll_is_enabled())
{
if (nrf_gzll_get_rx_fifo_packet_count(GZP_PAIRING_PIPE))
{
(void)nrf_gzll_fetch_packet_from_rx_fifo(GZP_PAIRING_PIPE, &gzp_req[0], &rx_payload_length);
// Validate step 1 of pairing request
if (gzp_req[0] == (uint8_t)GZP_CMD_HOST_ADDRESS_FETCH)
{
gzp_address_exchanged_f = true;
}
}
}
gzll_tx_fifo_flush();
gzll_rx_fifo_flush();
gzll_set_rx_timeout(0);
(void)nrf_gzll_set_rx_pipes_enabled(temp_rx_pipes);
// Return to normal operation
gzll_rx_start();
}
else
{
(void)nrf_gzll_set_rx_pipes_enabled(temp_rx_pipes & ~(1 << GZP_PAIRING_PIPE));
gzll_set_rx_timeout(GZP_NOT_PROXIMITY_BACKOFF_RX_TIMEOUT);
// Start "not proximity" backoff period
gzll_rx_start();
}
}
static void gzp_preload_ack(uint8_t* src, uint8_t length, uint8_t pipe)
{
gzll_goto_idle();
gzll_tx_fifo_flush();
(void)nrf_gzll_add_packet_to_tx_fifo(pipe, src, length);
gzll_rx_start();
}
static void gzll_set_rx_timeout(uint32_t timeout)
{
timeout *= 2; // * 2 as gzll_set_rx_timeout() takes RX_PERIODS as input, which equals 2 timeslots.
nrf_gzll_set_auto_disable(timeout);
}
bool gzp_address_exchanged()
{
return gzp_address_exchanged_f;
}
#ifndef GZP_CRYPT_DISABLE
bool gzp_crypt_user_data_received()
{
return (gzp_encrypted_user_data_length > 0);
}
bool gzp_crypt_user_data_read(uint8_t* dst, uint8_t* length)
{
if (gzp_encrypted_user_data_length > 0)
{
memcpy(dst, (void*)gzp_encrypted_user_data, gzp_encrypted_user_data_length);
if (length != NULL)
{
*length = gzp_encrypted_user_data_length;
}
gzp_encrypted_user_data_length = 0;
return true;
}
else
{
return false;
}
}
static void gzp_session_counter_inc()
{
uint8_t i;
for (i = 0; i < GZP_SESSION_TOKEN_LENGTH; i++)
{
gzp_session_counter[i]++;
if (gzp_session_counter[i] != 0)
{
break;
}
}
}
static void gzp_get_session_counter(uint8_t* dst)
{
memcpy(dst, (void*)gzp_session_counter, GZP_SESSION_TOKEN_LENGTH);
}
static void gzp_set_host_id(const uint8_t* src)
{
if (*((uint8_t*)database) == 0xff)
{
nrf_nvmc_write_bytes(GZP_PARAMS_STORAGE_ADR + 1, src, GZP_HOST_ID_LENGTH);
nrf_nvmc_write_byte(GZP_PARAMS_STORAGE_ADR, 0x00);
}
}
void gzp_get_host_id(uint8_t *dst)
{
memcpy(dst, (uint8_t*)GZP_PARAMS_STORAGE_ADR + 1, GZP_HOST_ID_LENGTH);
}
static void gzp_process_id_req(uint8_t* rx_payload)
{
int i;
uint8_t temp_host_id[GZP_HOST_ID_LENGTH];
if (gzp_pairing_enabled_f)
{
if (!gzp_id_req_received())
{
gzp_crypt_set_session_token(&rx_payload[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN]);
gzp_id_req_stat = GZP_ID_REQ_PENDING;
}
gzp_get_host_id(temp_host_id);
// Added:
for (i = 0; i < GZP_HOST_ID_LENGTH; i++)
{
if (temp_host_id[i] != 0xFF)
{
break;
}
}
if (i == GZP_HOST_ID_LENGTH) // If host not generated yet
{
gzp_get_session_counter(temp_host_id);
#if (GZP_HOST_ID_LENGTH > GZP_SESSION_TOKEN_LENGTH)
gzp_xor_cipher(temp_host_id, temp_host_id, &rx_payload[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN], GZP_SESSION_TOKEN_LENGTH);
#else //(GZP_HOST_ID_LENGTH > GZP_SESSION_TOKEN_LENGTH)
gzp_xor_cipher(temp_host_id, temp_host_id, &rx_payload[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN], GZP_HOST_ID_LENGTH);
#endif //(GZP_HOST_ID_LENGTH > GZP_SESSION_TOKEN_LENGTH)
gzp_set_host_id(temp_host_id);
}
}
}
static void gzp_process_id_fetch(uint8_t* rx_payload)
{
uint8_t tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH];
if (gzp_id_req_received())
{
gzp_crypt_select_key(GZP_ID_EXCHANGE);
gzp_crypt(&rx_payload[1], &rx_payload[1], GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH - 1);
if (gzp_validate_id(&rx_payload[GZP_CMD_HOST_ID_FETCH_VALIDATION_ID]))
{
switch (gzp_id_req_stat)
{
case GZP_ID_REQ_PENDING_AND_GRANTED:
tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_STATUS] = (uint8_t)GZP_ID_RESP_GRANTED;
gzp_get_host_id(&tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_HOST_ID]);
gzp_id_req_stat = GZP_ID_REQ_IDLE;
break;
case GZP_ID_REQ_PENDING_AND_REJECTED:
tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_STATUS] = (uint8_t)GZP_ID_RESP_REJECTED;
gzp_id_req_stat = GZP_ID_REQ_IDLE;
break;
case GZP_ID_REQ_PENDING:
default:
tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_STATUS] = (uint8_t)GZP_ID_RESP_PENDING;
break;
}
tx_payload[0] = (uint8_t)GZP_CMD_HOST_ID_FETCH_RESP;
gzp_add_validation_id(&tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_VALIDATION_ID]);
gzp_crypt(&tx_payload[1], &tx_payload[1], GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH - 1);
ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
gzp_preload_ack(tx_payload, GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH, GZP_DATA_PIPE);
ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
}
}
}
static void gzp_process_key_update_prepare()
{
uint8_t tx_payload[GZP_CMD_KEY_UPDATE_PREPARE_RESP_PAYLOAD_LENGTH];
tx_payload[0] = (uint8_t)GZP_CMD_KEY_UPDATE_PREPARE_RESP;
gzp_get_session_counter(&tx_payload[GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN]);
// Update session token if no ID request is pending
if (!gzp_id_req_received())
{
gzp_crypt_set_session_token(&tx_payload[GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN]);
}
gzp_preload_ack(tx_payload, GZP_CMD_KEY_UPDATE_PREPARE_RESP_PAYLOAD_LENGTH, GZP_DATA_PIPE);
ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
}
static void gzp_process_key_update(uint8_t* rx_payload)
{
gzp_crypt_select_key(GZP_KEY_EXCHANGE);
gzp_crypt(&rx_payload[1], &rx_payload[1], GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH - 1);
if (gzp_validate_id(&rx_payload[GZP_CMD_KEY_UPDATE_VALIDATION_ID]))
{
gzp_crypt_set_dyn_key(&rx_payload[GZP_CMD_KEY_UPDATE_NEW_KEY]);
}
}
static void gzp_process_encrypted_user_data(uint8_t* rx_payload, uint8_t length)
{
uint8_t tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_PAYLOAD_LENGTH];
if (gzp_id_req_received())
{
gzp_crypt_select_key(GZP_ID_EXCHANGE);
}
else
{
gzp_crypt_select_key(GZP_DATA_EXCHANGE);
}
gzp_crypt(&rx_payload[1], &rx_payload[1], length - 1);
if (gzp_validate_id(&rx_payload[GZP_CMD_ENCRYPTED_USER_DATA_VALIDATION_ID]))
{
gzp_encrypted_user_data_length = length - GZP_ENCRYPTED_USER_DATA_PACKET_OVERHEAD;
memcpy((void*)gzp_encrypted_user_data, &rx_payload[GZP_CMD_ENCRYPTED_USER_DATA_PAYLOAD], gzp_encrypted_user_data_length);
}
// Build response packet
tx_payload[0] = (uint8_t)GZP_CMD_ENCRYPTED_USER_DATA_RESP;
gzp_add_validation_id(&tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID]);
gzp_crypt(&tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID], &tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID], GZP_VALIDATION_ID_LENGTH);
gzp_get_session_counter(&tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_SESSION_TOKEN]);
// Update "session token" only if no ID request is pending
if (!gzp_id_req_received())
{
gzp_crypt_set_session_token(&tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_SESSION_TOKEN]);
}
ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
gzp_preload_ack(tx_payload, GZP_CMD_ENCRYPTED_USER_DATA_RESP_PAYLOAD_LENGTH, GZP_DATA_PIPE);
ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR);
}
//-----------------------------------------------------------------------------
// Function added during LE1 -> nRF51 port
//-----------------------------------------------------------------------------
static void gzll_goto_idle()
{
nrf_gzll_disable();
while (nrf_gzll_is_enabled())
{}
}
static void gzll_tx_fifo_flush(void)
{
int i;
for (i = 0; i < NRF_GZLL_CONST_PIPE_COUNT; i++)
{
(void)nrf_gzll_flush_tx_fifo(i);
}
}
static void gzll_rx_fifo_flush(void)
{
int i;
for (i = 0; i < NRF_GZLL_CONST_PIPE_COUNT; i++)
{
(void)nrf_gzll_flush_rx_fifo(i);
}
}
/******************************************************************************/
// Implementation: Gazell callback functions
/******************************************************************************/
void nrf_gzll_device_tx_failed(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info)
{
}
void nrf_gzll_device_tx_success(uint32_t pipe, nrf_gzll_device_tx_info_t tx_info)
{
}
void nrf_gzll_disabled(void)
{
}
void nrf_gzll_host_rx_data_ready(uint32_t pipe, nrf_gzll_host_rx_info_t rx_info)
{
if (pipe == GZP_PAIRING_PIPE)
{
prev_gzp_rx_info = rx_info;
}
}
/** @} */
/** @} */
#endif

View File

@@ -0,0 +1,74 @@
/**
* Copyright (c) 2009 - 2020, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "nrf_gzp.h"
#include "nrf_nvmc.h"
/**
* @file
* @brief Implementation of Gazell Pairing Library (gzp), nRF5x specific Host functions.
* @defgroup gzp_source_host_nrf5x Gazell Pairing Host nRF5x specific implementation
* @{
* @ingroup gzp_04_source
*/
void gzp_host_chip_id_read(uint8_t *dst, uint8_t n)
{
uint8_t i;
uint8_t random_number;
if ( *((uint8_t*)(GZP_PARAMS_STORAGE_ADR + GZP_HOST_ID_LENGTH + 1)) == 0xff)
{
nrf_nvmc_write_byte((GZP_PARAMS_STORAGE_ADR + GZP_HOST_ID_LENGTH + 1) , 0x00);
for (i = 0; i < n; i++)
{
gzp_random_numbers_generate(&random_number, 1);
nrf_nvmc_write_byte((GZP_PARAMS_STORAGE_ADR + GZP_HOST_ID_LENGTH + 2 + i) , random_number);
}
}
for (i = 0; i < n; i++)
{
*(dst++) = *((uint8_t*)(GZP_PARAMS_STORAGE_ADR + GZP_HOST_ID_LENGTH + 2 + i));
}
}
/** @} */