Add copy of hw/drivers/nimble (for controller build)

This commit is contained in:
Andrzej Kaczmarek
2017-12-20 17:46:30 +01:00
parent 359188d56d
commit c07f163323
13 changed files with 5464 additions and 0 deletions
+46
View File
@@ -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_ */
+30
View File
@@ -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
+239
View File
@@ -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
+632
View File
@@ -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)
{
}
+48
View File
@@ -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_ */
+31
View File
@@ -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
+482
View File
@@ -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
+52
View File
@@ -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_ */
+31
View File
@@ -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
+486
View File
@@ -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
+54
View File
@@ -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