mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-08-31 22:30:04 +00:00
Add copy of hw/drivers/nimble (for controller build)
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_XCVR_
|
||||
#define H_BLE_XCVR_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Transceiver specific defintions */
|
||||
#define XCVR_RX_START_DELAY_USECS (140)
|
||||
#define XCVR_TX_START_DELAY_USECS (140)
|
||||
#define XCVR_PROC_DELAY_USECS (100)
|
||||
#define XCVR_TX_SCHED_DELAY_USECS \
|
||||
(XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
|
||||
#define XCVR_RX_SCHED_DELAY_USECS \
|
||||
(XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
|
||||
|
||||
/*
|
||||
* Define HW whitelist size. This is the total possible whitelist size;
|
||||
* not necessarily the size that will be used (may be smaller)
|
||||
*/
|
||||
#define BLE_HW_WHITE_LIST_SIZE (0)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_XCVR_ */
|
||||
@@ -0,0 +1,30 @@
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
pkg.name: hw/drivers/nimble/native
|
||||
pkg.description: BLE driver for simulations.
|
||||
pkg.author: "Apache Mynewt <[email protected]>"
|
||||
pkg.homepage: "http://mynewt.apache.org/"
|
||||
pkg.keywords:
|
||||
- ble
|
||||
- bluetooth
|
||||
|
||||
pkg.apis: ble_driver
|
||||
pkg.deps:
|
||||
- net/nimble/controller
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "os/os.h"
|
||||
#include "nimble/ble.h"
|
||||
#include "nimble/nimble_opt.h"
|
||||
#include "controller/ble_hw.h"
|
||||
|
||||
/* Total number of white list elements supported by nrf52 */
|
||||
#define BLE_HW_WHITE_LIST_SIZE (0)
|
||||
|
||||
/* We use this to keep track of which entries are set to valid addresses */
|
||||
static uint8_t g_ble_hw_whitelist_mask;
|
||||
|
||||
/* Returns public device address or -1 if not present */
|
||||
int
|
||||
ble_hw_get_public_addr(ble_addr_t *addr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Returns random static address or -1 if not present */
|
||||
int
|
||||
ble_hw_get_static_addr(ble_addr_t *addr)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the whitelist
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_clear(void)
|
||||
{
|
||||
g_ble_hw_whitelist_mask = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a device to the hw whitelist
|
||||
*
|
||||
* @param addr
|
||||
* @param addr_type
|
||||
*
|
||||
* @return int 0: success, BLE error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type)
|
||||
{
|
||||
return BLE_ERR_MEM_CAPACITY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a device from the hw whitelist
|
||||
*
|
||||
* @param addr
|
||||
* @param addr_type
|
||||
*
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_rmv(uint8_t *addr, uint8_t addr_type)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the whitelist in HW
|
||||
*
|
||||
* @return int Number of devices allowed in whitelist
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_whitelist_size(void)
|
||||
{
|
||||
return BLE_HW_WHITE_LIST_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the whitelisted devices
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_enable(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the whitelisted devices
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_disable(void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean function which returns true ('1') if there is a match on the
|
||||
* whitelist.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_whitelist_match(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Encrypt data */
|
||||
int
|
||||
ble_hw_encrypt_block(struct ble_encryption_block *ecb)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the random number generator
|
||||
*
|
||||
* @param cb
|
||||
* @param bias
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the random number generator
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_start(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the random generator
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_stop(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the random number generator.
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_rng_read(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
|
||||
/**
|
||||
* Clear the resolving list
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
void
|
||||
ble_hw_resolv_list_clear(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a device to the hw resolving list
|
||||
*
|
||||
* @param irk Pointer to IRK to add
|
||||
*
|
||||
* @return int 0: success, BLE error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_hw_resolv_list_add(uint8_t *irk)
|
||||
{
|
||||
return BLE_ERR_MEM_CAPACITY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a device from the hw resolving list
|
||||
*
|
||||
* @param index Index of IRK to remove
|
||||
*/
|
||||
void
|
||||
ble_hw_resolv_list_rmv(int index)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the resolving list. NOTE: this returns the maximum
|
||||
* allowable entries in the HW. Configuration options may limit this.
|
||||
*
|
||||
* @return int Number of devices allowed in resolving list
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_resolv_list_size(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to determine if the address received was resolved.
|
||||
*
|
||||
* @return int Negative values indicate unresolved address; positive values
|
||||
* indicate index in resolving list of resolved address.
|
||||
*/
|
||||
int
|
||||
ble_hw_resolv_list_match(void)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,632 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "os/os.h"
|
||||
#include "ble/xcvr.h"
|
||||
#include "nimble/ble.h"
|
||||
#include "nimble/nimble_opt.h"
|
||||
#include "controller/ble_phy.h"
|
||||
#include "controller/ble_ll.h"
|
||||
|
||||
/* BLE PHY data structure */
|
||||
struct ble_phy_obj
|
||||
{
|
||||
uint8_t phy_stats_initialized;
|
||||
int8_t phy_txpwr_dbm;
|
||||
uint8_t phy_chan;
|
||||
uint8_t phy_state;
|
||||
uint8_t phy_transition;
|
||||
uint8_t phy_rx_started;
|
||||
uint8_t phy_encrypted;
|
||||
uint8_t phy_privacy;
|
||||
uint8_t phy_tx_pyld_len;
|
||||
uint32_t phy_aar_scratch;
|
||||
uint32_t phy_access_address;
|
||||
struct ble_mbuf_hdr rxhdr;
|
||||
void *txend_arg;
|
||||
uint8_t *rxdptr;
|
||||
ble_phy_tx_end_func txend_cb;
|
||||
};
|
||||
struct ble_phy_obj g_ble_phy_data;
|
||||
|
||||
/* Statistics */
|
||||
struct ble_phy_statistics
|
||||
{
|
||||
uint32_t tx_good;
|
||||
uint32_t tx_fail;
|
||||
uint32_t tx_late;
|
||||
uint32_t tx_bytes;
|
||||
uint32_t rx_starts;
|
||||
uint32_t rx_aborts;
|
||||
uint32_t rx_valid;
|
||||
uint32_t rx_crc_err;
|
||||
uint32_t phy_isrs;
|
||||
uint32_t radio_state_errs;
|
||||
uint32_t no_bufs;
|
||||
};
|
||||
|
||||
struct ble_phy_statistics g_ble_phy_stats;
|
||||
|
||||
/* XCVR object to emulate transceiver */
|
||||
struct xcvr_data
|
||||
{
|
||||
uint32_t irq_status;
|
||||
};
|
||||
static struct xcvr_data g_xcvr_data;
|
||||
|
||||
#define BLE_XCVR_IRQ_F_RX_START (0x00000001)
|
||||
#define BLE_XCVR_IRQ_F_RX_END (0x00000002)
|
||||
#define BLE_XCVR_IRQ_F_TX_START (0x00000004)
|
||||
#define BLE_XCVR_IRQ_F_TX_END (0x00000008)
|
||||
#define BLE_XCVR_IRQ_F_BYTE_CNTR (0x00000010)
|
||||
|
||||
/* "Rail" power level if outside supported range */
|
||||
#define BLE_XCVR_TX_PWR_MAX_DBM (30)
|
||||
#define BLE_XCVR_TX_PWR_MIN_DBM (-20)
|
||||
|
||||
/* Statistics */
|
||||
STATS_SECT_START(ble_phy_stats)
|
||||
STATS_SECT_ENTRY(phy_isrs)
|
||||
STATS_SECT_ENTRY(tx_good)
|
||||
STATS_SECT_ENTRY(tx_fail)
|
||||
STATS_SECT_ENTRY(tx_late)
|
||||
STATS_SECT_ENTRY(tx_bytes)
|
||||
STATS_SECT_ENTRY(rx_starts)
|
||||
STATS_SECT_ENTRY(rx_aborts)
|
||||
STATS_SECT_ENTRY(rx_valid)
|
||||
STATS_SECT_ENTRY(rx_crc_err)
|
||||
STATS_SECT_ENTRY(rx_late)
|
||||
STATS_SECT_ENTRY(no_bufs)
|
||||
STATS_SECT_ENTRY(radio_state_errs)
|
||||
STATS_SECT_ENTRY(rx_hw_err)
|
||||
STATS_SECT_ENTRY(tx_hw_err)
|
||||
STATS_SECT_END
|
||||
STATS_SECT_DECL(ble_phy_stats) ble_phy_stats;
|
||||
|
||||
STATS_NAME_START(ble_phy_stats)
|
||||
STATS_NAME(ble_phy_stats, phy_isrs)
|
||||
STATS_NAME(ble_phy_stats, tx_good)
|
||||
STATS_NAME(ble_phy_stats, tx_fail)
|
||||
STATS_NAME(ble_phy_stats, tx_late)
|
||||
STATS_NAME(ble_phy_stats, tx_bytes)
|
||||
STATS_NAME(ble_phy_stats, rx_starts)
|
||||
STATS_NAME(ble_phy_stats, rx_aborts)
|
||||
STATS_NAME(ble_phy_stats, rx_valid)
|
||||
STATS_NAME(ble_phy_stats, rx_crc_err)
|
||||
STATS_NAME(ble_phy_stats, rx_late)
|
||||
STATS_NAME(ble_phy_stats, no_bufs)
|
||||
STATS_NAME(ble_phy_stats, radio_state_errs)
|
||||
STATS_NAME(ble_phy_stats, rx_hw_err)
|
||||
STATS_NAME(ble_phy_stats, tx_hw_err)
|
||||
STATS_NAME_END(ble_phy_stats)
|
||||
|
||||
/* XXX: TODO:
|
||||
|
||||
* 1) Test the following to make sure it works: suppose an event is already
|
||||
* set to 1 and the interrupt is not enabled. What happens if you enable the
|
||||
* interrupt with the event bit already set to 1
|
||||
* 2) how to deal with interrupts?
|
||||
*/
|
||||
static uint32_t
|
||||
ble_xcvr_get_irq_status(void)
|
||||
{
|
||||
return g_xcvr_data.irq_status;
|
||||
}
|
||||
|
||||
static void
|
||||
ble_xcvr_clear_irq(uint32_t mask)
|
||||
{
|
||||
g_xcvr_data.irq_status &= ~mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the data from the phy receive buffer into a mbuf chain.
|
||||
*
|
||||
* @param dptr Pointer to receive buffer
|
||||
* @param rxpdu Pointer to already allocated mbuf chain
|
||||
*
|
||||
* NOTE: the packet header already has the total mbuf length in it. The
|
||||
* lengths of the individual mbufs are not set prior to calling.
|
||||
*
|
||||
*/
|
||||
void
|
||||
ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu)
|
||||
{
|
||||
uint16_t rem_bytes;
|
||||
uint16_t mb_bytes;
|
||||
uint16_t copylen;
|
||||
uint32_t *dst;
|
||||
uint32_t *src;
|
||||
struct os_mbuf *m;
|
||||
struct ble_mbuf_hdr *ble_hdr;
|
||||
struct os_mbuf_pkthdr *pkthdr;
|
||||
|
||||
/* Better be aligned */
|
||||
assert(((uint32_t)dptr & 3) == 0);
|
||||
|
||||
pkthdr = OS_MBUF_PKTHDR(rxpdu);
|
||||
rem_bytes = pkthdr->omp_len;
|
||||
|
||||
/* Fill in the mbuf pkthdr first. */
|
||||
dst = (uint32_t *)(rxpdu->om_data);
|
||||
src = (uint32_t *)dptr;
|
||||
|
||||
mb_bytes = (rxpdu->om_omp->omp_databuf_len - rxpdu->om_pkthdr_len - 4);
|
||||
copylen = min(mb_bytes, rem_bytes);
|
||||
copylen &= 0xFFFC;
|
||||
rem_bytes -= copylen;
|
||||
mb_bytes -= copylen;
|
||||
rxpdu->om_len = copylen;
|
||||
while (copylen > 0) {
|
||||
*dst = *src;
|
||||
++dst;
|
||||
++src;
|
||||
copylen -= 4;
|
||||
}
|
||||
|
||||
/* Copy remaining bytes */
|
||||
m = rxpdu;
|
||||
while (rem_bytes > 0) {
|
||||
/* If there are enough bytes in the mbuf, copy them and leave */
|
||||
if (rem_bytes <= mb_bytes) {
|
||||
memcpy(m->om_data + m->om_len, src, rem_bytes);
|
||||
m->om_len += rem_bytes;
|
||||
break;
|
||||
}
|
||||
|
||||
m = SLIST_NEXT(m, om_next);
|
||||
assert(m != NULL);
|
||||
|
||||
mb_bytes = m->om_omp->omp_databuf_len;
|
||||
copylen = min(mb_bytes, rem_bytes);
|
||||
copylen &= 0xFFFC;
|
||||
rem_bytes -= copylen;
|
||||
mb_bytes -= copylen;
|
||||
m->om_len = copylen;
|
||||
dst = (uint32_t *)m->om_data;
|
||||
while (copylen > 0) {
|
||||
*dst = *src;
|
||||
++dst;
|
||||
++src;
|
||||
copylen -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy ble header */
|
||||
ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
|
||||
memcpy(ble_hdr, &g_ble_phy_data.rxhdr, sizeof(struct ble_mbuf_hdr));
|
||||
}
|
||||
|
||||
void
|
||||
ble_phy_isr(void)
|
||||
{
|
||||
int rc;
|
||||
uint8_t transition;
|
||||
uint32_t irq_en;
|
||||
struct ble_mbuf_hdr *ble_hdr;
|
||||
|
||||
/* Check for disabled event. This only happens for transmits now */
|
||||
irq_en = ble_xcvr_get_irq_status();
|
||||
if (irq_en & BLE_XCVR_IRQ_F_TX_END) {
|
||||
|
||||
/* Better be in TX state! */
|
||||
assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX);
|
||||
ble_xcvr_clear_irq(BLE_XCVR_IRQ_F_TX_END);
|
||||
|
||||
transition = g_ble_phy_data.phy_transition;
|
||||
if (transition == BLE_PHY_TRANSITION_TX_RX) {
|
||||
/* Disable the phy */
|
||||
/* XXX: count no bufs? */
|
||||
ble_phy_disable();
|
||||
} else {
|
||||
/* Better not be going from rx to tx! */
|
||||
assert(transition == BLE_PHY_TRANSITION_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
/* We get this if we have started to receive a frame */
|
||||
if (irq_en & BLE_XCVR_IRQ_F_RX_START) {
|
||||
|
||||
ble_xcvr_clear_irq(BLE_XCVR_IRQ_F_RX_START);
|
||||
|
||||
/* Call Link Layer receive start function */
|
||||
rc = ble_ll_rx_start(g_ble_phy_data.rxdptr, g_ble_phy_data.phy_chan,
|
||||
&g_ble_phy_data.rxhdr);
|
||||
if (rc >= 0) {
|
||||
/* XXX: set rx end enable isr */
|
||||
} else {
|
||||
/* Disable PHY */
|
||||
ble_phy_disable();
|
||||
irq_en = 0;
|
||||
++g_ble_phy_stats.rx_aborts;
|
||||
}
|
||||
|
||||
/* Count rx starts */
|
||||
++g_ble_phy_stats.rx_starts;
|
||||
}
|
||||
|
||||
/* Receive packet end (we dont enable this for transmit) */
|
||||
if (irq_en & BLE_XCVR_IRQ_F_RX_END) {
|
||||
|
||||
ble_xcvr_clear_irq(BLE_XCVR_IRQ_F_RX_END);
|
||||
|
||||
/* Construct BLE header before handing up */
|
||||
ble_hdr = &g_ble_phy_data.rxhdr;
|
||||
ble_hdr->rxinfo.flags = 0;
|
||||
ble_hdr->rxinfo.rssi = -77; /* XXX: dummy rssi */
|
||||
ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan;
|
||||
ble_hdr->rxinfo.phy = BLE_PHY_1M;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
ble_hdr->rxinfo.aux_data = NULL;
|
||||
#endif
|
||||
|
||||
/* Count PHY valid packets */
|
||||
++g_ble_phy_stats.rx_valid;
|
||||
ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK;
|
||||
|
||||
/* Call Link Layer receive payload function */
|
||||
rc = ble_ll_rx_end(g_ble_phy_data.rxdptr, ble_hdr);
|
||||
if (rc < 0) {
|
||||
/* Disable the PHY. */
|
||||
ble_phy_disable();
|
||||
}
|
||||
}
|
||||
|
||||
/* Count # of interrupts */
|
||||
++g_ble_phy_stats.phy_isrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* ble phy init
|
||||
*
|
||||
* Initialize the PHY. This is expected to be called once.
|
||||
*
|
||||
* @return int 0: success; PHY error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_phy_init(void)
|
||||
{
|
||||
/* Set phy channel to an invalid channel so first set channel works */
|
||||
g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
|
||||
g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS;
|
||||
|
||||
/* XXX: emulate ISR? */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ble_phy_rx(void)
|
||||
{
|
||||
/* Check radio state */
|
||||
if (ble_phy_state_get() != BLE_PHY_STATE_IDLE) {
|
||||
ble_phy_disable();
|
||||
++g_ble_phy_stats.radio_state_errs;
|
||||
return BLE_PHY_ERR_RADIO_STATE;
|
||||
}
|
||||
|
||||
g_ble_phy_data.phy_state = BLE_PHY_STATE_RX;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ble_phy_restart_rx(void)
|
||||
{
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
|
||||
/**
|
||||
* Called to enable encryption at the PHY. Note that this state will persist
|
||||
* in the PHY; in other words, if you call this function you have to call
|
||||
* disable so that future PHY transmits/receives will not be encrypted.
|
||||
*
|
||||
* @param pkt_counter
|
||||
* @param iv
|
||||
* @param key
|
||||
* @param is_master
|
||||
*/
|
||||
void
|
||||
ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key,
|
||||
uint8_t is_master)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ble_phy_encrypt_disable(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg)
|
||||
{
|
||||
/* Set transmit end callback and arg */
|
||||
g_ble_phy_data.txend_cb = txend_cb;
|
||||
g_ble_phy_data.txend_arg = arg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to set the start time of a transmission.
|
||||
*
|
||||
* This function is called to set the start time when we are not going from
|
||||
* rx to tx automatically.
|
||||
*
|
||||
* NOTE: care must be taken when calling this function. The channel should
|
||||
* already be set.
|
||||
*
|
||||
* @param cputime
|
||||
* @param rem_usecs
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to set the start time of a reception
|
||||
*
|
||||
* This function acts a bit differently than transmit. If we are late getting
|
||||
* here we will still attempt to receive.
|
||||
*
|
||||
* NOTE: care must be taken when calling this function. The channel should
|
||||
* already be set.
|
||||
*
|
||||
* @param cputime
|
||||
* @param rem_usecs
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Better have a pdu! */
|
||||
assert(txpdu != NULL);
|
||||
|
||||
if (ble_phy_state_get() != BLE_PHY_STATE_IDLE) {
|
||||
ble_phy_disable();
|
||||
++g_ble_phy_stats.radio_state_errs;
|
||||
return BLE_PHY_ERR_RADIO_STATE;
|
||||
}
|
||||
|
||||
/* Select tx address */
|
||||
if (g_ble_phy_data.phy_chan < BLE_PHY_NUM_DATA_CHANS) {
|
||||
/* XXX: fix this */
|
||||
assert(0);
|
||||
} else {
|
||||
}
|
||||
|
||||
/* Set the PHY transition */
|
||||
g_ble_phy_data.phy_transition = end_trans;
|
||||
|
||||
/* Set phy state to transmitting and count packet statistics */
|
||||
g_ble_phy_data.phy_state = BLE_PHY_STATE_TX;
|
||||
++g_ble_phy_stats.tx_good;
|
||||
g_ble_phy_stats.tx_bytes += OS_MBUF_PKTHDR(txpdu)->omp_len +
|
||||
BLE_LL_PDU_HDR_LEN;
|
||||
rc = BLE_ERR_SUCCESS;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* ble phy txpwr set
|
||||
*
|
||||
* Set the transmit output power (in dBm).
|
||||
*
|
||||
* NOTE: If the output power specified is within the BLE limits but outside
|
||||
* the chip limits, we "rail" the power level so we dont exceed the min/max
|
||||
* chip values.
|
||||
*
|
||||
* @param dbm Power output in dBm.
|
||||
*
|
||||
* @return int 0: success; anything else is an error
|
||||
*/
|
||||
int
|
||||
ble_phy_txpwr_set(int dbm)
|
||||
{
|
||||
/* Check valid range */
|
||||
assert(dbm <= BLE_PHY_MAX_PWR_DBM);
|
||||
|
||||
/* "Rail" power level if outside supported range */
|
||||
if (dbm > BLE_XCVR_TX_PWR_MAX_DBM) {
|
||||
dbm = BLE_XCVR_TX_PWR_MAX_DBM;
|
||||
} else {
|
||||
if (dbm < BLE_XCVR_TX_PWR_MIN_DBM) {
|
||||
dbm = BLE_XCVR_TX_PWR_MIN_DBM;
|
||||
}
|
||||
}
|
||||
|
||||
g_ble_phy_data.phy_txpwr_dbm = dbm;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ble phy txpwr round
|
||||
*
|
||||
* Get the rounded transmit output power (in dBm).
|
||||
*
|
||||
* @param dbm Power output in dBm.
|
||||
*
|
||||
* @return int Rounded power in dBm
|
||||
*/
|
||||
int ble_phy_txpower_round(int dbm)
|
||||
{
|
||||
/* "Rail" power level if outside supported range */
|
||||
if (dbm > BLE_XCVR_TX_PWR_MAX_DBM) {
|
||||
dbm = BLE_XCVR_TX_PWR_MAX_DBM;
|
||||
} else {
|
||||
if (dbm < BLE_XCVR_TX_PWR_MIN_DBM) {
|
||||
dbm = BLE_XCVR_TX_PWR_MIN_DBM;
|
||||
}
|
||||
}
|
||||
|
||||
return dbm;
|
||||
}
|
||||
|
||||
/**
|
||||
* ble phy txpwr get
|
||||
*
|
||||
* Get the transmit power.
|
||||
*
|
||||
* @return int The current PHY transmit power, in dBm
|
||||
*/
|
||||
int
|
||||
ble_phy_txpwr_get(void)
|
||||
{
|
||||
return g_ble_phy_data.phy_txpwr_dbm;
|
||||
}
|
||||
|
||||
/**
|
||||
* ble phy setchan
|
||||
*
|
||||
* Sets the logical frequency of the transceiver. The input parameter is the
|
||||
* BLE channel index (0 to 39, inclusive). The NRF52 frequency register
|
||||
* works like this: logical frequency = 2400 + FREQ (MHz).
|
||||
*
|
||||
* Thus, to get a logical frequency of 2402 MHz, you would program the
|
||||
* FREQUENCY register to 2.
|
||||
*
|
||||
* @param chan This is the Data Channel Index or Advertising Channel index
|
||||
*
|
||||
* @return int 0: success; PHY error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit)
|
||||
{
|
||||
assert(chan < BLE_PHY_NUM_CHANS);
|
||||
|
||||
/* Check for valid channel range */
|
||||
if (chan >= BLE_PHY_NUM_CHANS) {
|
||||
return BLE_PHY_ERR_INV_PARAM;
|
||||
}
|
||||
|
||||
g_ble_phy_data.phy_access_address = access_addr;
|
||||
|
||||
g_ble_phy_data.phy_chan = chan;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the PHY. This will do the following:
|
||||
* -> Turn off all phy interrupts.
|
||||
* -> Disable internal shortcuts.
|
||||
* -> Disable the radio.
|
||||
* -> Sets phy state to idle.
|
||||
*/
|
||||
void
|
||||
ble_phy_disable(void)
|
||||
{
|
||||
g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
|
||||
}
|
||||
|
||||
/* Gets the current access address */
|
||||
uint32_t ble_phy_access_addr_get(void)
|
||||
{
|
||||
return g_ble_phy_data.phy_access_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the phy state
|
||||
*
|
||||
* @return int The current PHY state.
|
||||
*/
|
||||
int
|
||||
ble_phy_state_get(void)
|
||||
{
|
||||
return g_ble_phy_data.phy_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to see if a reception has started
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_phy_rx_started(void)
|
||||
{
|
||||
return g_ble_phy_data.phy_rx_started;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to return the maximum data pdu payload length supported by the
|
||||
* phy. For this chip, if encryption is enabled, the maximum payload is 27
|
||||
* bytes.
|
||||
*
|
||||
* @return uint8_t Maximum data channel PDU payload size supported
|
||||
*/
|
||||
uint8_t
|
||||
ble_phy_max_data_pdu_pyld(void)
|
||||
{
|
||||
return BLE_LL_DATA_PDU_MAX_PYLD;
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
|
||||
void
|
||||
ble_phy_resolv_list_enable(void)
|
||||
{
|
||||
g_ble_phy_data.phy_privacy = 1;
|
||||
}
|
||||
|
||||
void
|
||||
ble_phy_resolv_list_disable(void)
|
||||
{
|
||||
g_ble_phy_data.phy_privacy = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the transceiver state
|
||||
*
|
||||
* @return int transceiver state.
|
||||
*/
|
||||
uint8_t
|
||||
ble_phy_xcvr_state_get(void)
|
||||
{
|
||||
return g_ble_phy_data.phy_state;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs)
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_XCVR_
|
||||
#define H_BLE_XCVR_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Transceiver specific defintions */
|
||||
/* NOTE: we have to account for the RTC output compare issue */
|
||||
#define XCVR_PROC_DELAY_USECS (230)
|
||||
|
||||
#define XCVR_RX_START_DELAY_USECS (140)
|
||||
#define XCVR_TX_START_DELAY_USECS (140)
|
||||
#define XCVR_TX_SCHED_DELAY_USECS \
|
||||
(XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
|
||||
#define XCVR_RX_SCHED_DELAY_USECS \
|
||||
(XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
|
||||
|
||||
/*
|
||||
* Define HW whitelist size. This is the total possible whitelist size;
|
||||
* not necessarily the size that will be used (may be smaller)
|
||||
*/
|
||||
#define BLE_HW_WHITE_LIST_SIZE (8)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_XCVR_ */
|
||||
@@ -0,0 +1,31 @@
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
pkg.name: hw/drivers/nimble/nrf51
|
||||
pkg.description: BLE driver for nRF51 systems.
|
||||
pkg.author: "Apache Mynewt <[email protected]>"
|
||||
pkg.homepage: "http://mynewt.apache.org/"
|
||||
pkg.keywords:
|
||||
- ble
|
||||
- bluetooth
|
||||
|
||||
pkg.apis: ble_driver
|
||||
pkg.deps:
|
||||
- net/nimble
|
||||
- net/nimble/controller
|
||||
@@ -0,0 +1,482 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "os/os.h"
|
||||
#include "ble/xcvr.h"
|
||||
#include "nimble/ble.h"
|
||||
#include "nimble/nimble_opt.h"
|
||||
#include "nrf51_bitfields.h"
|
||||
#include "controller/ble_hw.h"
|
||||
#include "bsp/cmsis_nvic.h"
|
||||
|
||||
/* Total number of resolving list elements */
|
||||
#define BLE_HW_RESOLV_LIST_SIZE (16)
|
||||
|
||||
/* We use this to keep track of which entries are set to valid addresses */
|
||||
static uint8_t g_ble_hw_whitelist_mask;
|
||||
|
||||
/* Random number generator isr callback */
|
||||
ble_rng_isr_cb_t g_ble_rng_isr_cb;
|
||||
|
||||
/* If LL privacy is enabled, allocate memory for AAR */
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
|
||||
|
||||
/* The NRF51 supports up to 16 IRK entries */
|
||||
#if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16)
|
||||
#define NRF_IRK_LIST_ENTRIES (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE))
|
||||
#else
|
||||
#define NRF_IRK_LIST_ENTRIES (16)
|
||||
#endif
|
||||
|
||||
/* NOTE: each entry is 16 bytes long. */
|
||||
uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4];
|
||||
|
||||
/* Current number of IRK entries */
|
||||
uint8_t g_nrf_num_irks;
|
||||
|
||||
#endif
|
||||
|
||||
/* Returns public device address or -1 if not present */
|
||||
int
|
||||
ble_hw_get_public_addr(ble_addr_t *addr)
|
||||
{
|
||||
int rc;
|
||||
uint32_t addr_high;
|
||||
uint32_t addr_low;
|
||||
|
||||
/* Does FICR have a public address */
|
||||
rc = -1;
|
||||
if ((NRF_FICR->DEVICEADDRTYPE & 1) == 0) {
|
||||
addr_low = NRF_FICR->DEVICEADDR[0];
|
||||
addr_high = NRF_FICR->DEVICEADDR[1];
|
||||
rc = 0;
|
||||
} else {
|
||||
/* See if programmed in UICR. Upper 16 bits must all be zero */
|
||||
addr_high = NRF_UICR->CUSTOMER[1];
|
||||
if (addr_high < 65536) {
|
||||
addr_low = NRF_UICR->CUSTOMER[0];
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rc) {
|
||||
/* Copy into device address. We can do this because we know platform */
|
||||
memcpy(addr->val, &addr_low, 4);
|
||||
memcpy(&addr->val[4], &addr_high, 2);
|
||||
addr->type = BLE_ADDR_PUBLIC;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Returns random static address or -1 if not present */
|
||||
int
|
||||
ble_hw_get_static_addr(ble_addr_t *addr)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if ((NRF_FICR->DEVICEADDRTYPE & 1) == 1) {
|
||||
memcpy(addr->val, (void *)&NRF_FICR->DEVICEADDR[0], 4);
|
||||
memcpy(&addr->val[4], (void *)&NRF_FICR->DEVICEADDR[1], 2);
|
||||
addr->val[5] |= 0xc0;
|
||||
addr->type = BLE_ADDR_RANDOM;
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the whitelist
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_clear(void)
|
||||
{
|
||||
NRF_RADIO->DACNF = 0;
|
||||
g_ble_hw_whitelist_mask = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a device to the hw whitelist
|
||||
*
|
||||
* @param addr
|
||||
* @param addr_type
|
||||
*
|
||||
* @return int 0: success, BLE error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type)
|
||||
{
|
||||
int i;
|
||||
uint32_t mask;
|
||||
|
||||
/* Find first ununsed device address match element */
|
||||
mask = 0x01;
|
||||
for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
|
||||
if ((mask & g_ble_hw_whitelist_mask) == 0) {
|
||||
NRF_RADIO->DAB[i] = get_le32(addr);
|
||||
NRF_RADIO->DAP[i] = get_le16(addr + 4);
|
||||
if (addr_type == BLE_ADDR_RANDOM) {
|
||||
NRF_RADIO->DACNF |= (mask << 8);
|
||||
}
|
||||
g_ble_hw_whitelist_mask |= mask;
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
return BLE_ERR_MEM_CAPACITY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a device from the hw whitelist
|
||||
*
|
||||
* @param addr
|
||||
* @param addr_type
|
||||
*
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_rmv(uint8_t *addr, uint8_t addr_type)
|
||||
{
|
||||
int i;
|
||||
uint8_t cfg_addr;
|
||||
uint16_t dap;
|
||||
uint16_t txadd;
|
||||
uint32_t dab;
|
||||
uint32_t mask;
|
||||
|
||||
/* Find first ununsed device address match element */
|
||||
dab = get_le32(addr);
|
||||
dap = get_le16(addr + 4);
|
||||
txadd = NRF_RADIO->DACNF >> 8;
|
||||
mask = 0x01;
|
||||
for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
|
||||
if (mask & g_ble_hw_whitelist_mask) {
|
||||
if ((dab == NRF_RADIO->DAB[i]) && (dap == NRF_RADIO->DAP[i])) {
|
||||
cfg_addr = txadd & mask;
|
||||
if (addr_type == BLE_ADDR_RANDOM) {
|
||||
if (cfg_addr != 0) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (cfg_addr == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
if (i < BLE_HW_WHITE_LIST_SIZE) {
|
||||
g_ble_hw_whitelist_mask &= ~mask;
|
||||
NRF_RADIO->DACNF &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the whitelist in HW
|
||||
*
|
||||
* @return int Number of devices allowed in whitelist
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_whitelist_size(void)
|
||||
{
|
||||
return BLE_HW_WHITE_LIST_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the whitelisted devices
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_enable(void)
|
||||
{
|
||||
/* Enable the configured device addresses */
|
||||
NRF_RADIO->DACNF |= g_ble_hw_whitelist_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the whitelisted devices
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_disable(void)
|
||||
{
|
||||
/* Disable all whitelist devices */
|
||||
NRF_RADIO->DACNF &= 0x0000ff00;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean function which returns true ('1') if there is a match on the
|
||||
* whitelist.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_whitelist_match(void)
|
||||
{
|
||||
return (int)NRF_RADIO->EVENTS_DEVMATCH;
|
||||
}
|
||||
|
||||
/* Encrypt data */
|
||||
int
|
||||
ble_hw_encrypt_block(struct ble_encryption_block *ecb)
|
||||
{
|
||||
int rc;
|
||||
uint32_t end;
|
||||
uint32_t err;
|
||||
|
||||
/* Stop ECB */
|
||||
NRF_ECB->TASKS_STOPECB = 1;
|
||||
/* XXX: does task stop clear these counters? Anyway to do this quicker? */
|
||||
NRF_ECB->EVENTS_ENDECB = 0;
|
||||
NRF_ECB->EVENTS_ERRORECB = 0;
|
||||
NRF_ECB->ECBDATAPTR = (uint32_t)ecb;
|
||||
|
||||
/* Start ECB */
|
||||
NRF_ECB->TASKS_STARTECB = 1;
|
||||
|
||||
/* Wait till error or done */
|
||||
rc = 0;
|
||||
while (1) {
|
||||
end = NRF_ECB->EVENTS_ENDECB;
|
||||
err = NRF_ECB->EVENTS_ERRORECB;
|
||||
if (end || err) {
|
||||
if (err) {
|
||||
rc = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Random number generator ISR.
|
||||
*/
|
||||
static void
|
||||
ble_rng_isr(void)
|
||||
{
|
||||
uint8_t rnum;
|
||||
|
||||
/* No callback? Clear and disable interrupts */
|
||||
if (g_ble_rng_isr_cb == NULL) {
|
||||
NRF_RNG->INTENCLR = 1;
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
(void)NRF_RNG->SHORTS;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If there is a value ready grab it */
|
||||
if (NRF_RNG->EVENTS_VALRDY) {
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
rnum = (uint8_t)NRF_RNG->VALUE;
|
||||
(*g_ble_rng_isr_cb)(rnum);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the random number generator
|
||||
*
|
||||
* @param cb
|
||||
* @param bias
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
|
||||
{
|
||||
/* Set bias */
|
||||
if (bias) {
|
||||
NRF_RNG->CONFIG = 1;
|
||||
} else {
|
||||
NRF_RNG->CONFIG = 0;
|
||||
}
|
||||
|
||||
/* If we were passed a function pointer we need to enable the interrupt */
|
||||
if (cb != NULL) {
|
||||
NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
|
||||
NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr);
|
||||
NVIC_EnableIRQ(RNG_IRQn);
|
||||
g_ble_rng_isr_cb = cb;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the random number generator
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_start(void)
|
||||
{
|
||||
os_sr_t sr;
|
||||
|
||||
/* No need for interrupt if there is no callback */
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
if (g_ble_rng_isr_cb) {
|
||||
NRF_RNG->INTENSET = 1;
|
||||
}
|
||||
NRF_RNG->TASKS_START = 1;
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the random generator
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_stop(void)
|
||||
{
|
||||
os_sr_t sr;
|
||||
|
||||
/* No need for interrupt if there is no callback */
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
NRF_RNG->INTENCLR = 1;
|
||||
NRF_RNG->TASKS_STOP = 1;
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the random number generator.
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_rng_read(void)
|
||||
{
|
||||
uint8_t rnum;
|
||||
|
||||
/* Wait for a sample */
|
||||
while (NRF_RNG->EVENTS_VALRDY == 0) {
|
||||
}
|
||||
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
rnum = (uint8_t)NRF_RNG->VALUE;
|
||||
|
||||
return rnum;
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY))
|
||||
/**
|
||||
* Clear the resolving list
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
void
|
||||
ble_hw_resolv_list_clear(void)
|
||||
{
|
||||
g_nrf_num_irks = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a device to the hw resolving list
|
||||
*
|
||||
* @param irk Pointer to IRK to add
|
||||
*
|
||||
* @return int 0: success, BLE error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_hw_resolv_list_add(uint8_t *irk)
|
||||
{
|
||||
uint32_t *nrf_entry;
|
||||
|
||||
/* Find first ununsed device address match element */
|
||||
if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) {
|
||||
return BLE_ERR_MEM_CAPACITY;
|
||||
}
|
||||
|
||||
/* Copy into irk list */
|
||||
nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks];
|
||||
memcpy(nrf_entry, irk, 16);
|
||||
|
||||
/* Add to total */
|
||||
++g_nrf_num_irks;
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a device from the hw resolving list
|
||||
*
|
||||
* @param index Index of IRK to remove
|
||||
*/
|
||||
void
|
||||
ble_hw_resolv_list_rmv(int index)
|
||||
{
|
||||
uint32_t *irk_entry;
|
||||
|
||||
if (index < g_nrf_num_irks) {
|
||||
--g_nrf_num_irks;
|
||||
irk_entry = &g_nrf_irk_list[index];
|
||||
if (g_nrf_num_irks > index) {
|
||||
memmove(irk_entry, irk_entry + 4, g_nrf_num_irks - index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the resolving list. NOTE: this returns the maximum
|
||||
* allowable entries in the HW. Configuration options may limit this.
|
||||
*
|
||||
* @return int Number of devices allowed in resolving list
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_resolv_list_size(void)
|
||||
{
|
||||
return BLE_HW_RESOLV_LIST_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to determine if the address received was resolved.
|
||||
*
|
||||
* @return int Negative values indicate unresolved address; positive values
|
||||
* indicate index in resolving list of resolved address.
|
||||
*/
|
||||
int
|
||||
ble_hw_resolv_list_match(void)
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
if (NRF_AAR->EVENTS_END) {
|
||||
if (NRF_AAR->EVENTS_RESOLVED) {
|
||||
index = NRF_AAR->STATUS;
|
||||
return (int)index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_XCVR_
|
||||
#define H_BLE_XCVR_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define XCVR_RX_RADIO_RAMPUP_USECS (40)
|
||||
#define XCVR_TX_RADIO_RAMPUP_USECS (40)
|
||||
|
||||
/*
|
||||
* NOTE: we have to account for the RTC output compare issue. We want it to be
|
||||
* 5 ticks.
|
||||
*/
|
||||
#define XCVR_PROC_DELAY_USECS (153)
|
||||
#define XCVR_RX_START_DELAY_USECS (XCVR_RX_RADIO_RAMPUP_USECS)
|
||||
#define XCVR_TX_START_DELAY_USECS (XCVR_TX_RADIO_RAMPUP_USECS)
|
||||
#define XCVR_TX_SCHED_DELAY_USECS \
|
||||
(XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
|
||||
#define XCVR_RX_SCHED_DELAY_USECS \
|
||||
(XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
|
||||
|
||||
/*
|
||||
* Define HW whitelist size. This is the total possible whitelist size;
|
||||
* not necessarily the size that will be used (may be smaller)
|
||||
*/
|
||||
#define BLE_HW_WHITE_LIST_SIZE (8)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_XCVR_ */
|
||||
@@ -0,0 +1,31 @@
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
pkg.name: hw/drivers/nimble/nrf52
|
||||
pkg.description: BLE driver for nRF52 systems.
|
||||
pkg.author: "Apache Mynewt <[email protected]>"
|
||||
pkg.homepage: "http://mynewt.apache.org/"
|
||||
pkg.keywords:
|
||||
- ble
|
||||
- bluetooth
|
||||
|
||||
pkg.apis: ble_driver
|
||||
pkg.deps:
|
||||
- net/nimble
|
||||
- net/nimble/controller
|
||||
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "os/os.h"
|
||||
#include "ble/xcvr.h"
|
||||
#include "nimble/ble.h"
|
||||
#include "nimble/nimble_opt.h"
|
||||
#include "nrf52_bitfields.h"
|
||||
#include "controller/ble_hw.h"
|
||||
#include "bsp/cmsis_nvic.h"
|
||||
#include "os/os_trace_api.h"
|
||||
|
||||
/* Total number of resolving list elements */
|
||||
#define BLE_HW_RESOLV_LIST_SIZE (16)
|
||||
|
||||
/* We use this to keep track of which entries are set to valid addresses */
|
||||
static uint8_t g_ble_hw_whitelist_mask;
|
||||
|
||||
/* Random number generator isr callback */
|
||||
ble_rng_isr_cb_t g_ble_rng_isr_cb;
|
||||
|
||||
/* If LL privacy is enabled, allocate memory for AAR */
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
|
||||
|
||||
/* The NRF51 supports up to 16 IRK entries */
|
||||
#if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16)
|
||||
#define NRF_IRK_LIST_ENTRIES (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE))
|
||||
#else
|
||||
#define NRF_IRK_LIST_ENTRIES (16)
|
||||
#endif
|
||||
|
||||
/* NOTE: each entry is 16 bytes long. */
|
||||
uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4];
|
||||
|
||||
/* Current number of IRK entries */
|
||||
uint8_t g_nrf_num_irks;
|
||||
|
||||
#endif
|
||||
|
||||
/* Returns public device address or -1 if not present */
|
||||
int
|
||||
ble_hw_get_public_addr(ble_addr_t *addr)
|
||||
{
|
||||
int rc;
|
||||
uint32_t addr_high;
|
||||
uint32_t addr_low;
|
||||
|
||||
/* Does FICR have a public address */
|
||||
rc = -1;
|
||||
if ((NRF_FICR->DEVICEADDRTYPE & 1) == 0) {
|
||||
addr_low = NRF_FICR->DEVICEADDR[0];
|
||||
addr_high = NRF_FICR->DEVICEADDR[1];
|
||||
rc = 0;
|
||||
} else {
|
||||
/* See if programmed in UICR. Upper 16 bits must all be zero */
|
||||
addr_high = NRF_UICR->CUSTOMER[1];
|
||||
if (addr_high < 65536) {
|
||||
addr_low = NRF_UICR->CUSTOMER[0];
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!rc) {
|
||||
/* Copy into device address. We can do this because we know platform */
|
||||
memcpy(addr->val, &addr_low, 4);
|
||||
memcpy(&addr->val[4], &addr_high, 2);
|
||||
addr->type = BLE_ADDR_PUBLIC;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Returns random static address or -1 if not present */
|
||||
int
|
||||
ble_hw_get_static_addr(ble_addr_t *addr)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if ((NRF_FICR->DEVICEADDRTYPE & 1) == 1) {
|
||||
memcpy(addr->val, (void *)&NRF_FICR->DEVICEADDR[0], 4);
|
||||
memcpy(&addr->val[4], (void *)&NRF_FICR->DEVICEADDR[1], 2);
|
||||
addr->val[5] |= 0xc0;
|
||||
addr->type = BLE_ADDR_RANDOM;
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the whitelist
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_clear(void)
|
||||
{
|
||||
NRF_RADIO->DACNF = 0;
|
||||
g_ble_hw_whitelist_mask = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a device to the hw whitelist
|
||||
*
|
||||
* @param addr
|
||||
* @param addr_type
|
||||
*
|
||||
* @return int 0: success, BLE error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_hw_whitelist_add(uint8_t *addr, uint8_t addr_type)
|
||||
{
|
||||
int i;
|
||||
uint32_t mask;
|
||||
|
||||
/* Find first ununsed device address match element */
|
||||
mask = 0x01;
|
||||
for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
|
||||
if ((mask & g_ble_hw_whitelist_mask) == 0) {
|
||||
NRF_RADIO->DAB[i] = get_le32(addr);
|
||||
NRF_RADIO->DAP[i] = get_le16(addr + 4);
|
||||
if (addr_type == BLE_ADDR_RANDOM) {
|
||||
NRF_RADIO->DACNF |= (mask << 8);
|
||||
}
|
||||
g_ble_hw_whitelist_mask |= mask;
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
return BLE_ERR_MEM_CAPACITY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a device from the hw whitelist
|
||||
*
|
||||
* @param addr
|
||||
* @param addr_type
|
||||
*
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_rmv(uint8_t *addr, uint8_t addr_type)
|
||||
{
|
||||
int i;
|
||||
uint8_t cfg_addr;
|
||||
uint16_t dap;
|
||||
uint16_t txadd;
|
||||
uint32_t dab;
|
||||
uint32_t mask;
|
||||
|
||||
/* Find first ununsed device address match element */
|
||||
dab = get_le32(addr);
|
||||
dap = get_le16(addr + 4);
|
||||
txadd = NRF_RADIO->DACNF >> 8;
|
||||
mask = 0x01;
|
||||
for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
|
||||
if (mask & g_ble_hw_whitelist_mask) {
|
||||
if ((dab == NRF_RADIO->DAB[i]) && (dap == NRF_RADIO->DAP[i])) {
|
||||
cfg_addr = txadd & mask;
|
||||
if (addr_type == BLE_ADDR_RANDOM) {
|
||||
if (cfg_addr != 0) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (cfg_addr == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
if (i < BLE_HW_WHITE_LIST_SIZE) {
|
||||
g_ble_hw_whitelist_mask &= ~mask;
|
||||
NRF_RADIO->DACNF &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the whitelist in HW
|
||||
*
|
||||
* @return int Number of devices allowed in whitelist
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_whitelist_size(void)
|
||||
{
|
||||
return BLE_HW_WHITE_LIST_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the whitelisted devices
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_enable(void)
|
||||
{
|
||||
/* Enable the configured device addresses */
|
||||
NRF_RADIO->DACNF |= g_ble_hw_whitelist_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the whitelisted devices
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_disable(void)
|
||||
{
|
||||
/* Disable all whitelist devices */
|
||||
NRF_RADIO->DACNF &= 0x0000ff00;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean function which returns true ('1') if there is a match on the
|
||||
* whitelist.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_whitelist_match(void)
|
||||
{
|
||||
return (int)NRF_RADIO->EVENTS_DEVMATCH;
|
||||
}
|
||||
|
||||
/* Encrypt data */
|
||||
int
|
||||
ble_hw_encrypt_block(struct ble_encryption_block *ecb)
|
||||
{
|
||||
int rc;
|
||||
uint32_t end;
|
||||
uint32_t err;
|
||||
|
||||
/* Stop ECB */
|
||||
NRF_ECB->TASKS_STOPECB = 1;
|
||||
/* XXX: does task stop clear these counters? Anyway to do this quicker? */
|
||||
NRF_ECB->EVENTS_ENDECB = 0;
|
||||
NRF_ECB->EVENTS_ERRORECB = 0;
|
||||
NRF_ECB->ECBDATAPTR = (uint32_t)ecb;
|
||||
|
||||
/* Start ECB */
|
||||
NRF_ECB->TASKS_STARTECB = 1;
|
||||
|
||||
/* Wait till error or done */
|
||||
rc = 0;
|
||||
while (1) {
|
||||
end = NRF_ECB->EVENTS_ENDECB;
|
||||
err = NRF_ECB->EVENTS_ERRORECB;
|
||||
if (end || err) {
|
||||
if (err) {
|
||||
rc = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Random number generator ISR.
|
||||
*/
|
||||
static void
|
||||
ble_rng_isr(void)
|
||||
{
|
||||
uint8_t rnum;
|
||||
|
||||
os_trace_enter_isr();
|
||||
|
||||
/* No callback? Clear and disable interrupts */
|
||||
if (g_ble_rng_isr_cb == NULL) {
|
||||
NRF_RNG->INTENCLR = 1;
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
(void)NRF_RNG->SHORTS;
|
||||
return;
|
||||
}
|
||||
|
||||
/* If there is a value ready grab it */
|
||||
if (NRF_RNG->EVENTS_VALRDY) {
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
rnum = (uint8_t)NRF_RNG->VALUE;
|
||||
(*g_ble_rng_isr_cb)(rnum);
|
||||
}
|
||||
os_trace_exit_isr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the random number generator
|
||||
*
|
||||
* @param cb
|
||||
* @param bias
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
|
||||
{
|
||||
/* Set bias */
|
||||
if (bias) {
|
||||
NRF_RNG->CONFIG = 1;
|
||||
} else {
|
||||
NRF_RNG->CONFIG = 0;
|
||||
}
|
||||
|
||||
/* If we were passed a function pointer we need to enable the interrupt */
|
||||
if (cb != NULL) {
|
||||
NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
|
||||
NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr);
|
||||
NVIC_EnableIRQ(RNG_IRQn);
|
||||
g_ble_rng_isr_cb = cb;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the random number generator
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_start(void)
|
||||
{
|
||||
os_sr_t sr;
|
||||
|
||||
/* No need for interrupt if there is no callback */
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
if (g_ble_rng_isr_cb) {
|
||||
NRF_RNG->INTENSET = 1;
|
||||
}
|
||||
NRF_RNG->TASKS_START = 1;
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the random generator
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_stop(void)
|
||||
{
|
||||
os_sr_t sr;
|
||||
|
||||
/* No need for interrupt if there is no callback */
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
NRF_RNG->INTENCLR = 1;
|
||||
NRF_RNG->TASKS_STOP = 1;
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the random number generator.
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_rng_read(void)
|
||||
{
|
||||
uint8_t rnum;
|
||||
|
||||
/* Wait for a sample */
|
||||
while (NRF_RNG->EVENTS_VALRDY == 0) {
|
||||
}
|
||||
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
rnum = (uint8_t)NRF_RNG->VALUE;
|
||||
|
||||
return rnum;
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY))
|
||||
/**
|
||||
* Clear the resolving list
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
void
|
||||
ble_hw_resolv_list_clear(void)
|
||||
{
|
||||
g_nrf_num_irks = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a device to the hw resolving list
|
||||
*
|
||||
* @param irk Pointer to IRK to add
|
||||
*
|
||||
* @return int 0: success, BLE error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_hw_resolv_list_add(uint8_t *irk)
|
||||
{
|
||||
uint32_t *nrf_entry;
|
||||
|
||||
/* Find first ununsed device address match element */
|
||||
if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) {
|
||||
return BLE_ERR_MEM_CAPACITY;
|
||||
}
|
||||
|
||||
/* Copy into irk list */
|
||||
nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks];
|
||||
memcpy(nrf_entry, irk, 16);
|
||||
|
||||
/* Add to total */
|
||||
++g_nrf_num_irks;
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a device from the hw resolving list
|
||||
*
|
||||
* @param index Index of IRK to remove
|
||||
*/
|
||||
void
|
||||
ble_hw_resolv_list_rmv(int index)
|
||||
{
|
||||
uint32_t *irk_entry;
|
||||
|
||||
if (index < g_nrf_num_irks) {
|
||||
--g_nrf_num_irks;
|
||||
irk_entry = &g_nrf_irk_list[index];
|
||||
if (g_nrf_num_irks > index) {
|
||||
memmove(irk_entry, irk_entry + 4, g_nrf_num_irks - index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the resolving list. NOTE: this returns the maximum
|
||||
* allowable entries in the HW. Configuration options may limit this.
|
||||
*
|
||||
* @return int Number of devices allowed in resolving list
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_resolv_list_size(void)
|
||||
{
|
||||
return BLE_HW_RESOLV_LIST_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to determine if the address received was resolved.
|
||||
*
|
||||
* @return int Negative values indicate unresolved address; positive values
|
||||
* indicate index in resolving list of resolved address.
|
||||
*/
|
||||
int
|
||||
ble_hw_resolv_list_match(void)
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
if (NRF_AAR->EVENTS_END) {
|
||||
if (NRF_AAR->EVENTS_RESOLVED) {
|
||||
index = NRF_AAR->STATUS;
|
||||
return (int)index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,54 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
# Package: hw/drivers/nimble/nrf52
|
||||
|
||||
syscfg.defs:
|
||||
BLE_PHY_CODED_RX_IFS_EXTRA_MARGIN:
|
||||
description: >
|
||||
This defines additional margin for T_IFS tolerance while in
|
||||
RX on coded phy to allow maintaining connections with some
|
||||
controllers that exceed proper T_IFS (150 usecs) by more
|
||||
than allowed 2 usecs.
|
||||
This value shall be only used for debugging purposes. It is
|
||||
strongly recommended to keep this settings at default value
|
||||
to ensure compliance with specification.
|
||||
value: 0
|
||||
BLE_PHY_DBG_TIME_TXRXEN_READY_PIN:
|
||||
description: >
|
||||
When set to proper GPIO pin number, this pin will be set
|
||||
to high state when radio is enabled using PPI channels
|
||||
20 or 21 and back to low state on radio EVENTS_READY.
|
||||
This can be used to measure radio ram-up time.
|
||||
value: -1
|
||||
|
||||
BLE_PHY_DBG_TIME_ADDRESS_END_PIN:
|
||||
description: >
|
||||
When set to proper GPIO pin number, this pin will be set
|
||||
to high state on radio EVENTS_ADDRESS and back to low state
|
||||
on radio EVENTS_END.
|
||||
This can be used to measure radio pipeline delays.
|
||||
value: -1
|
||||
|
||||
BLE_PHY_DBG_TIME_WFR_PIN:
|
||||
description: >
|
||||
When set to proper GPIO pin number, this pin will be set
|
||||
to high state on radio EVENTS_RXREADY and back to low
|
||||
state when wfr timer expires.
|
||||
This can be used to check if wfr is calculated properly.
|
||||
value: -1
|
||||
Reference in New Issue
Block a user