You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by we...@apache.org on 2017/03/30 21:45:04 UTC
[1/5] incubator-mynewt-core git commit: nimble/controller: Slight
refactor of use of pkt receive time
Repository: incubator-mynewt-core
Updated Branches:
refs/heads/develop 9b6c2847d -> 244227b77
nimble/controller: Slight refactor of use of pkt receive time
Modified the code so that the packet receive time is used in less
places. No functionality change.
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/8158805c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/8158805c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/8158805c
Branch: refs/heads/develop
Commit: 8158805cd5d86b3fb17365065425711f0cb6b7ea
Parents: 9b6c284
Author: William San Filippo <wi...@runtime.io>
Authored: Thu Jan 19 14:57:21 2017 -0800
Committer: William San Filippo <wi...@runtime.io>
Committed: Thu Mar 30 14:09:04 2017 -0700
----------------------------------------------------------------------
.../controller/include/controller/ble_ll_conn.h | 2 +-
net/nimble/controller/src/ble_ll_adv.c | 7 +------
net/nimble/controller/src/ble_ll_conn.c | 21 ++++++++------------
net/nimble/controller/src/ble_ll_conn_priv.h | 2 +-
4 files changed, 11 insertions(+), 21 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8158805c/net/nimble/controller/include/controller/ble_ll_conn.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_conn.h b/net/nimble/controller/include/controller/ble_ll_conn.h
index d0badff..b2e6410 100644
--- a/net/nimble/controller/include/controller/ble_ll_conn.h
+++ b/net/nimble/controller/include/controller/ble_ll_conn.h
@@ -202,7 +202,7 @@ struct ble_ll_conn_sm
uint16_t max_ce_len;
uint16_t tx_win_off;
uint32_t anchor_point;
- uint32_t last_anchor_point;
+ uint32_t last_anchor_point; /* Slave only */
uint32_t slave_cur_tx_win_usecs;
uint32_t slave_cur_window_widening;
uint32_t last_rxd_pdu_cputime; /* Used exclusively for supervision timer */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8158805c/net/nimble/controller/src/ble_ll_adv.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_adv.c b/net/nimble/controller/src/ble_ll_adv.c
index 1130638..203f13a 100644
--- a/net/nimble/controller/src/ble_ll_adv.c
+++ b/net/nimble/controller/src/ble_ll_adv.c
@@ -1209,14 +1209,12 @@ ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr,
struct ble_ll_adv_sm *advsm)
{
int valid;
- uint8_t pyld_len;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
uint8_t resolved;
#endif
uint8_t addr_type;
uint8_t *inita;
uint8_t *ident_addr;
- uint32_t endtime;
/* Check filter policy. */
valid = 0;
@@ -1275,10 +1273,7 @@ ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr,
#endif
/* Try to start slave connection. If successful, stop advertising */
- pyld_len = rxbuf[1] & BLE_ADV_PDU_HDR_LEN_MASK;
- endtime = hdr->beg_cputime +
- os_cputime_usecs_to_ticks(BLE_TX_DUR_USECS_M(pyld_len));
- valid = ble_ll_conn_slave_start(rxbuf, endtime, addr_type, hdr);
+ valid = ble_ll_conn_slave_start(rxbuf, addr_type, hdr);
if (valid) {
ble_ll_adv_sm_stop(advsm);
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8158805c/net/nimble/controller/src/ble_ll_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn.c b/net/nimble/controller/src/ble_ll_conn.c
index 171d938..1d2714a 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -1770,11 +1770,11 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
* @ return 0: connection NOT created. 1: connection created
*/
static int
-ble_ll_conn_created(struct ble_ll_conn_sm *connsm, uint32_t endtime,
- struct ble_mbuf_hdr *rxhdr)
+ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr)
{
int rc;
uint8_t *evbuf;
+ uint32_t endtime;
uint32_t usecs;
/* Set state to created */
@@ -1798,8 +1798,10 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, uint32_t endtime,
* the transmit window offset from the end of the connection request.
*/
rc = 1;
- connsm->last_anchor_point = endtime;
if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
+ endtime = rxhdr->beg_cputime +
+ os_cputime_usecs_to_ticks(BLE_TX_DUR_USECS_M(BLE_CONNECT_REQ_LEN));
+ connsm->last_anchor_point = endtime;
connsm->slave_cur_tx_win_usecs =
connsm->tx_win_size * BLE_LL_CONN_TX_WIN_USECS;
usecs = 1250 + (connsm->tx_win_off * BLE_LL_CONN_TX_WIN_USECS);
@@ -2169,9 +2171,7 @@ ble_ll_init_rx_pkt_in(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr)
int8_t rpa_index;
#endif
uint8_t addr_type;
- uint8_t payload_len;
uint8_t *addr;
- uint32_t endtime;
struct ble_ll_conn_sm *connsm;
/* Get the connection state machine we are trying to create */
@@ -2216,10 +2216,7 @@ ble_ll_init_rx_pkt_in(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr)
/* Connection has been created. Stop scanning */
g_ble_ll_conn_create_sm = NULL;
ble_ll_scan_sm_stop(0);
- payload_len = rxbuf[1] & BLE_ADV_PDU_HDR_LEN_MASK;
- endtime = ble_hdr->beg_cputime +
- os_cputime_usecs_to_ticks(BLE_TX_DUR_USECS_M(payload_len));
- ble_ll_conn_created(connsm, endtime, NULL);
+ ble_ll_conn_created(connsm, NULL);
} else {
ble_ll_scan_chk_resume();
}
@@ -3053,8 +3050,7 @@ ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, uint8_t *chanmap)
* @return 0: connection not started; 1 connecton started
*/
int
-ble_ll_conn_slave_start(uint8_t *rxbuf, uint32_t conn_req_end, uint8_t pat,
- struct ble_mbuf_hdr *rxhdr)
+ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat, struct ble_mbuf_hdr *rxhdr)
{
int rc;
uint32_t temp;
@@ -3147,8 +3143,7 @@ ble_ll_conn_slave_start(uint8_t *rxbuf, uint32_t conn_req_end, uint8_t pat,
/* Set initial schedule callback */
connsm->conn_sch.sched_cb = ble_ll_conn_event_start_cb;
-
- rc = ble_ll_conn_created(connsm, conn_req_end, rxhdr);
+ rc = ble_ll_conn_created(connsm, rxhdr);
if (!rc) {
SLIST_REMOVE(&g_ble_ll_conn_active_list, connsm, ble_ll_conn_sm, act_sle);
STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8158805c/net/nimble/controller/src/ble_ll_conn_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn_priv.h b/net/nimble/controller/src/ble_ll_conn_priv.h
index f3ede51..0913892 100644
--- a/net/nimble/controller/src/ble_ll_conn_priv.h
+++ b/net/nimble/controller/src/ble_ll_conn_priv.h
@@ -103,7 +103,7 @@ void ble_ll_conn_datalen_update(struct ble_ll_conn_sm *connsm,
struct ble_ll_len_req *req);
/* Advertising interface */
-int ble_ll_conn_slave_start(uint8_t *rxbuf, uint32_t conn_req_end, uint8_t pat,
+int ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat,
struct ble_mbuf_hdr *rxhdr);
/* Link Layer interface */
[4/5] incubator-mynewt-core git commit: MYNEWT-701: Low power timer
support
Posted by we...@apache.org.
MYNEWT-701: Low power timer support
This commit adds low power timer support to the controller for
the nordic chips. Please see the Jira ticket for more information.
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/3c785953
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/3c785953
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/3c785953
Branch: refs/heads/develop
Commit: 3c7859538a63df76d170fb5cc30cac902f13a7b0
Parents: 507f493
Author: William San Filippo <wi...@runtime.io>
Authored: Thu Mar 30 13:30:57 2017 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Thu Mar 30 14:10:22 2017 -0700
----------------------------------------------------------------------
hw/drivers/nimble/nrf51/include/ble/xcvr.h | 11 +-
hw/drivers/nimble/nrf51/src/ble_phy.c | 440 +++++++++++++++++--
hw/drivers/nimble/nrf52/src/ble_phy.c | 5 +
kernel/os/src/os_cputime.c | 13 +-
.../controller/include/controller/ble_ll.h | 2 +-
net/nimble/controller/src/ble_ll_conn.c | 6 +-
6 files changed, 434 insertions(+), 43 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3c785953/hw/drivers/nimble/nrf51/include/ble/xcvr.h
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/nrf51/include/ble/xcvr.h b/hw/drivers/nimble/nrf51/include/ble/xcvr.h
index 0736506..9f15271 100644
--- a/hw/drivers/nimble/nrf51/include/ble/xcvr.h
+++ b/hw/drivers/nimble/nrf51/include/ble/xcvr.h
@@ -25,9 +25,18 @@ extern "C" {
#endif
/* Transceiver specific defintions */
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+/*
+ * NOTE: we have to account for the RTC output compare issue, which is why
+ * this number is much larger when using the 32.768 crystal.
+ */
+#define XCVR_PROC_DELAY_USECS (230)
+#else
+#define XCVR_PROC_DELAY_USECS (100)
+#endif
+
#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 \
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3c785953/hw/drivers/nimble/nrf51/src/ble_phy.c
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/nrf51/src/ble_phy.c b/hw/drivers/nimble/nrf51/src/ble_phy.c
index d6ca388..c9e2b74 100644
--- a/hw/drivers/nimble/nrf51/src/ble_phy.c
+++ b/hw/drivers/nimble/nrf51/src/ble_phy.c
@@ -22,6 +22,7 @@
#include <assert.h>
#include "syscfg/syscfg.h"
#include "os/os.h"
+#include "ble/xcvr.h"
#include "bsp/cmsis_nvic.h"
#include "nimble/ble.h"
#include "nimble/nimble_opt.h"
@@ -84,6 +85,9 @@ struct ble_phy_obj
struct ble_mbuf_hdr rxhdr;
void *txend_arg;
ble_phy_tx_end_func txend_cb;
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ uint32_t phy_start_cputime;
+#endif
};
struct ble_phy_obj g_ble_phy_data;
@@ -278,6 +282,133 @@ nrf_wait_disabled(void)
}
}
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+/**
+ *
+ *
+ */
+int
+ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs)
+{
+ uint32_t next_cc;
+ uint32_t cur_cc;
+ uint32_t cntr;
+ uint32_t delta;
+
+ /*
+ * XXX: The TXEN time is 140 usecs but there may be additional delays
+ * Need to look at this.
+ */
+
+ /*
+ * With the 32.768 kHz crystal, we may need to adjust the RTC compare
+ * value by 1 tick due to the time it takes for TXEN. The code uses a 5 RTC
+ * tick offset, which is 152.5 usecs. The TXEN time is 140 usecs. This
+ * means that with a remainder of 0, TIMER0 should be set to 12 or 13 (as
+ * TIMER0 counts at 1MHz). A remainder of 19 or more we will need to add
+ * 1 tick. We dont need to add 1 tick per se, but it does give us slightly
+ * more time and thus less of a chance to miss a tick. Another note: we
+ * cant set TIMER0 CC to 0 as the compare wont occur; it must be 1 or more.
+ * This is why we subtract 18 (as opposed to 19) as rem_uses will be >= 1.
+ */
+ if (rem_usecs <= 18) {
+ cputime -= 5;
+ rem_usecs += 12;
+ } else {
+ cputime -= 4;
+ rem_usecs -= 18;
+ }
+
+ /*
+ * Can we set the RTC compare to start TIMER0? We can do it if:
+ * a) Current compare value is not N+1 or N+2 ticks from current
+ * counter.
+ * b) The value we want to set is not at least N+2 from current
+ * counter.
+ *
+ * NOTE: since the counter can tick 1 while we do these calculations we
+ * need to account for it.
+ */
+ next_cc = cputime & 0xffffff;
+ cur_cc = NRF_RTC0->CC[0];
+ cntr = NRF_RTC0->COUNTER;
+
+ delta = (cur_cc - cntr) & 0xffffff;
+ if ((delta <= 3) && (delta != 0)) {
+ return -1;
+ }
+ delta = (next_cc - cntr) & 0xffffff;
+ if ((delta & 0x800000) || (delta < 3)) {
+ return -1;
+ }
+
+ /* Clear and set TIMER0 to fire off at proper time */
+ NRF_TIMER0->TASKS_CLEAR = 1;
+ NRF_TIMER0->CC[0] = rem_usecs;
+ NRF_TIMER0->EVENTS_COMPARE[0] = 0;
+
+ /* Set RTC compare to start TIMER0 */
+ NRF_RTC0->EVENTS_COMPARE[0] = 0;
+ NRF_RTC0->CC[0] = next_cc;
+ NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
+
+ /* Enable PPI */
+ NRF_PPI->CHENSET = PPI_CHEN_CH31_Msk;
+
+ /* Store the cputime at which we set the RTC */
+ g_ble_phy_data.phy_start_cputime = cputime;
+
+ return 0;
+}
+
+/**
+ * Function is used to set PPI so that we can time out waiting for a reception
+ * to occur. This happens for two reasons: we have sent a packet and we are
+ * waiting for a respons (txrx should be set to ENABLE_TXRX) or we are
+ * starting a connection event and we are a slave and we are waiting for the
+ * master to send us a packet (txrx should be set to ENABLE_RX).
+ *
+ * NOTE: when waiting for a txrx turn-around, wfr_usecs is not used as there
+ * is no additional time to wait; we know when we should receive the address of
+ * the received frame.
+ *
+ * @param txrx Flag denoting if this wfr is a txrx turn-around or not.
+ * @param wfr_usecs Amount of usecs to wait.
+ */
+void
+ble_phy_wfr_enable(int txrx, uint32_t wfr_usecs)
+{
+ uint32_t end_time;
+
+ if (txrx == BLE_PHY_WFR_ENABLE_TXRX) {
+ /*
+ * Timeout occurs an IFS time plus time it takes to receive address
+ * from the transmit end. We add additional time to make sure the
+ * address event comes before the compare. Note that transmit end
+ * is captured in CC[2]
+ *
+ * XXX: this assumes 1Mbps as 40 usecs is header rx time for 1Mbps
+ */
+ end_time = NRF_TIMER0->CC[2] + BLE_LL_IFS + 40 + 16;
+ } else {
+ /* CC[0] is set to when RXEN occurs. NOTE: the extra 16 usecs is
+ jitter */
+ end_time = NRF_TIMER0->CC[0] + XCVR_RX_START_DELAY_USECS + wfr_usecs +
+ 40 + 16;
+ }
+
+ /* wfr_secs is the time from rxen until timeout */
+ NRF_TIMER0->CC[3] = end_time;
+ NRF_TIMER0->EVENTS_COMPARE[3] = 0;
+
+ /* Enable wait for response PPI */
+ NRF_PPI->CHENSET = (PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk);
+
+ /* Enable the disabled interrupt so we time out on events compare */
+ NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk;
+}
+#endif
+
/**
* Setup transceiver for receive.
*/
@@ -368,14 +499,18 @@ ble_phy_tx_end_isr(void)
uint8_t transition;
uint8_t txlen;
uint32_t wfr_time;
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) != 32768)
uint32_t txstart;
+#endif
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) != 32768)
/*
* Read captured tx start time. This is not the actual transmit start
* time but it is the time at which the address event occurred
* (after transmission of access address)
*/
txstart = NRF_TIMER0->CC[1];
+#endif
/* If this transmission was encrypted we need to remember it */
was_encrypted = g_ble_phy_data.phy_encrypted;
@@ -384,14 +519,20 @@ ble_phy_tx_end_isr(void)
assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX);
/* Log the event */
- ble_ll_log(BLE_LL_LOG_ID_PHY_TXEND, (g_ble_phy_tx_buf[0] >> 8) & 0xFF,
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
+ ble_ll_log(BLE_LL_LOG_ID_PHY_TXEND, g_ble_phy_data.phy_tx_pyld_len,
+ was_encrypted, NRF_TIMER0->CC[2]);
+#else
+ ble_ll_log(BLE_LL_LOG_ID_PHY_TXEND, g_ble_phy_data.phy_tx_pyld_len,
was_encrypted, txstart);
+#endif
/* Clear events and clear interrupt on disabled event */
NRF_RADIO->EVENTS_DISABLED = 0;
NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk;
NRF_RADIO->EVENTS_END = 0;
wfr_time = NRF_RADIO->SHORTS;
+ (void)wfr_time;
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
/*
@@ -424,13 +565,28 @@ ble_phy_tx_end_isr(void)
if (txlen && was_encrypted) {
txlen += BLE_LL_DATA_MIC_LEN;
}
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
+ ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_TXRX, 0);
+#else
wfr_time = BLE_LL_WFR_USECS - BLE_TX_LEN_USECS_M(NRF_RX_START_OFFSET);
wfr_time += BLE_TX_DUR_USECS_M(txlen);
wfr_time = os_cputime_usecs_to_ticks(wfr_time);
ble_ll_wfr_enable(txstart + wfr_time);
+#endif
} else {
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
+ /*
+ * XXX: not sure we need to stop the timer here all the time. Or that
+ * it should be stopped here.
+ */
+ NRF_TIMER0->TASKS_STOP = 1;
+ NRF_TIMER0->TASKS_SHUTDOWN = 1;
+ NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk |
+ PPI_CHEN_CH20_Msk | PPI_CHEN_CH31_Msk;
+#else
/* Disable automatic TXEN */
NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk;
+#endif
assert(transition == BLE_PHY_TRANSITION_NONE);
}
}
@@ -518,11 +674,48 @@ ble_phy_rx_start_isr(void)
{
int rc;
uint32_t state;
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ uint32_t usecs;
+ uint32_t ticks;
+#endif
struct ble_mbuf_hdr *ble_hdr;
/* Clear events and clear interrupt */
NRF_RADIO->EVENTS_ADDRESS = 0;
+
+ /* Clear wfr timer channels and DISABLED interrupt */
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk | RADIO_INTENCLR_ADDRESS_Msk;
+ NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk;
+#else
NRF_RADIO->INTENCLR = RADIO_INTENCLR_ADDRESS_Msk;
+#endif
+
+ /* Initialize flags, channel and state in ble header at rx start */
+ ble_hdr = &g_ble_phy_data.rxhdr;
+ ble_hdr->rxinfo.flags = ble_ll_state_get();
+ ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan;
+ ble_hdr->rxinfo.handle = 0;
+
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
+ /*
+ * Calculate receive start time. We assume that the header time is
+ * 40 usecs (only 1 mbps supported right now).
+ *
+ * XXX: possibly use other routine with remainder!
+ */
+ usecs = NRF_TIMER0->CC[1] - 40;
+ ticks = os_cputime_usecs_to_ticks(usecs);
+ ble_hdr->rem_usecs = usecs - os_cputime_ticks_to_usecs(ticks);
+ if (ble_hdr->rem_usecs == 31) {
+ ble_hdr->rem_usecs = 0;
+ ++ticks;
+ }
+ ble_hdr->beg_cputime = g_ble_phy_data.phy_start_cputime + ticks;
+#else
+ ble_hdr->beg_cputime = NRF_TIMER0->CC[1] -
+ os_cputime_usecs_to_ticks(BLE_TX_LEN_USECS_M(NRF_RX_START_OFFSET));
+#endif
/* Wait to get 1st byte of frame */
while (1) {
@@ -542,14 +735,6 @@ ble_phy_rx_start_isr(void)
}
}
- /* Initialize flags, channel and state in ble header at rx start */
- ble_hdr = &g_ble_phy_data.rxhdr;
- ble_hdr->rxinfo.flags = ble_ll_state_get();
- ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan;
- ble_hdr->rxinfo.handle = 0;
- ble_hdr->beg_cputime = NRF_TIMER0->CC[1] -
- os_cputime_usecs_to_ticks(BLE_TX_LEN_USECS_M(NRF_RX_START_OFFSET));
-
/* 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);
@@ -584,16 +769,34 @@ ble_phy_isr(void)
/* Read irq register to determine which interrupts are enabled */
irq_en = NRF_RADIO->INTENCLR;
- /* Check for disabled event. This only happens for transmits now */
- if ((irq_en & RADIO_INTENCLR_DISABLED_Msk) && NRF_RADIO->EVENTS_DISABLED) {
- ble_phy_tx_end_isr();
- }
+ /*
+ * NOTE: order of checking is important! Possible, if things get delayed,
+ * we have both an ADDRESS and DISABLED interrupt in rx state. If we get
+ * an address, we disable the DISABLED interrupt.
+ */
/* We get this if we have started to receive a frame */
if ((irq_en & RADIO_INTENCLR_ADDRESS_Msk) && NRF_RADIO->EVENTS_ADDRESS) {
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ irq_en &= ~RADIO_INTENCLR_DISABLED_Msk;
+#endif
ble_phy_rx_start_isr();
}
+ /* Check for disabled event. This only happens for transmits now */
+ if ((irq_en & RADIO_INTENCLR_DISABLED_Msk) && NRF_RADIO->EVENTS_DISABLED) {
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ if (g_ble_phy_data.phy_state == BLE_PHY_STATE_RX) {
+ NRF_RADIO->EVENTS_DISABLED = 0;
+ ble_ll_wfr_timer_exp(NULL);
+ } else {
+ ble_phy_tx_end_isr();
+ }
+#else
+ ble_phy_tx_end_isr();
+#endif
+ }
+
/* Receive packet end (we dont enable this for transmit) */
if ((irq_en & RADIO_INTENCLR_END_Msk) && NRF_RADIO->EVENTS_END) {
ble_phy_rx_end_isr();
@@ -617,6 +820,8 @@ int
ble_phy_init(void)
{
int rc;
+
+#if !defined(BLE_XCVR_RFCLK)
uint32_t os_tmo;
/* Make sure HFXO is started */
@@ -631,6 +836,7 @@ ble_phy_init(void)
return BLE_PHY_ERR_INIT;
}
}
+#endif
/* Set phy channel to an invalid channel so first set channel works */
g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS;
@@ -665,8 +871,13 @@ ble_phy_init(void)
/* Configure IFS */
NRF_RADIO->TIFS = BLE_LL_IFS;
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ /* Captures tx/rx start in timer0 cc 1 and tx/rx end in timer0 cc 2 */
+ NRF_PPI->CHENSET = PPI_CHEN_CH26_Msk | PPI_CHEN_CH27_Msk;
+#else
/* Captures tx/rx start in timer0 capture 1 */
NRF_PPI->CHENSET = PPI_CHEN_CH26_Msk;
+#endif
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
NRF_CCM->INTENCLR = 0xffffffff;
@@ -685,6 +896,27 @@ ble_phy_init(void)
NRF_AAR->NIRK = 0;
#endif
+ /* TIMER0 setup for PHY when using RTC */
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
+ NRF_TIMER0->TASKS_STOP = 1;
+ NRF_TIMER0->TASKS_SHUTDOWN = 1;
+ NRF_TIMER0->BITMODE = 3; /* 32-bit timer */
+ NRF_TIMER0->MODE = 0; /* Timer mode */
+ NRF_TIMER0->PRESCALER = 4; /* gives us 1 MHz */
+
+ /*
+ * PPI setup.
+ * Channel 4: Captures TIMER0 in CC[3] when EVENTS_ADDRESS occurs. Used
+ * to cancel the wait for response timer.
+ * Channel 5: TIMER0 CC[3] to TASKS_DISABLE on radio. This is the wait
+ * for response timer.
+ */
+ NRF_PPI->CH[4].EEP = (uint32_t)&(NRF_RADIO->EVENTS_ADDRESS);
+ NRF_PPI->CH[4].TEP = (uint32_t)&(NRF_TIMER0->TASKS_CAPTURE[3]);
+ NRF_PPI->CH[5].EEP = (uint32_t)&(NRF_TIMER0->EVENTS_COMPARE[3]);
+ NRF_PPI->CH[5].TEP = (uint32_t)&(NRF_RADIO->TASKS_DISABLE);
+#endif
+
/* Set isr in vector table and enable interrupt */
NVIC_SetPriority(RADIO_IRQn, 0);
NVIC_SetVector(RADIO_IRQn, (uint32_t)ble_phy_isr);
@@ -803,6 +1035,7 @@ ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg)
g_ble_phy_data.txend_arg = arg;
}
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
/**
* Called to set the start time of a transmission.
*
@@ -812,28 +1045,38 @@ ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg)
* NOTE: care must be taken when calling this function. The channel should
* already be set.
*
- * @param cputime
- *
+ * @param cputime This is the tick at which the 1st bit of the preamble
+ * should be transmitted
+ * @param rem_usecs This is used only when the underlying timing uses a 32.768
+ * kHz crystal. It is the # of usecs from the cputime tick
+ * at which the first bit of the preamble should be
+ * transmitted.
* @return int
*/
int
-ble_phy_tx_set_start_time(uint32_t cputime)
+ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
{
int rc;
- NRF_TIMER0->CC[0] = cputime;
- NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk;
+ /* XXX: This should not be necessary, but paranoia is good! */
+ /* Clear timer0 compare to RXEN since we are transmitting */
NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
- if ((int32_t)(os_cputime_get32() - cputime) >= 0) {
+
+ /*
+ * XXX: The TXEN time is 140 usecs but there may be additional delays
+ * Need to look at this.
+ */
+ if (ble_phy_set_start_time(cputime, rem_usecs) != 0) {
STATS_INC(ble_phy_stats, tx_late);
ble_phy_disable();
- rc = BLE_PHY_ERR_TX_LATE;
+ rc = BLE_PHY_ERR_TX_LATE;
} else {
+ /* Enable PPI to automatically start TXEN */
+ NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk;
rc = 0;
}
return rc;
}
-
/**
* Called to set the start time of a reception
*
@@ -848,23 +1091,91 @@ ble_phy_tx_set_start_time(uint32_t cputime)
* @return int
*/
int
-ble_phy_rx_set_start_time(uint32_t cputime)
+ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
{
int rc;
+ /* XXX: This should not be necessary, but paranoia is good! */
+ /* Clear timer0 compare to TXEN since we are transmitting */
+ NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk;
+
+ /*
+ * XXX: The RXEN time is 138 usecs but there may be additional delays
+ * Need to look at this.
+ */
+ if (ble_phy_set_start_time(cputime, rem_usecs) != 0) {
+ STATS_INC(ble_phy_stats, rx_late);
+ NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
+ NRF_RADIO->TASKS_RXEN = 1;
+ rc = BLE_PHY_ERR_RX_LATE;
+ } else {
+ /* Enable PPI to automatically start RXEN */
+ NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk;
+
+ /* Start rx */
+ rc = ble_phy_rx();
+ }
+ return rc;
+}
+#else
+/**
+ * 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 This is the tick at which the 1st bit of the preamble
+ * should be transmitted
+ * @return int
+ */
+int
+ble_phy_tx_set_start_time(uint32_t cputime)
+{
+ int rc;
+
+ cputime -= os_cputime_usecs_to_ticks(XCVR_TX_START_DELAY_USECS);
+ NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
NRF_TIMER0->CC[0] = cputime;
+ NRF_TIMER0->EVENTS_COMPARE[0] = 0;
+ NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk;
+ if ((int32_t)(os_cputime_get32() - cputime) >= 0) {
+ STATS_INC(ble_phy_stats, tx_late);
+ ble_phy_disable();
+ rc = BLE_PHY_ERR_TX_LATE;
+ } else {
+ rc = 0;
+ }
+
+ return rc;
+}
+
+#if 0
+int
+ble_phy_rx_set_start_time(void)
+{
+ /*
+ * XXX: For now, we dont use this function if we are not using the
+ * RTC. Keeping the code around just in case we want to use it later.
+ */
NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk;
+ NRF_TIMER0->CC[0] = cputime;
+ NRF_TIMER0->EVENTS_COMPARE[0] = 0;
NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk;
if ((int32_t)(os_cputime_get32() - cputime) >= 0) {
STATS_INC(ble_phy_stats, rx_late);
NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
NRF_RADIO->TASKS_RXEN = 1;
- rc = BLE_PHY_ERR_TX_LATE;
+ rc = BLE_PHY_ERR_RX_LATE;
} else {
rc = 0;
}
return rc;
}
+#endif
+#endif
int
ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans)
@@ -888,6 +1199,16 @@ ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans)
ble_hdr = BLE_MBUF_HDR_PTR(txpdu);
payload_len = ble_hdr->txinfo.pyld_len;
+ /*
+ * XXX: Although we may not have to do this here, I clear all the PPI
+ * that should not be used when transmitting. Some of them are only enabled
+ * if encryption and/or privacy is on, but I dont care. Better to be
+ * paranoid, and if you are going to clear one, might as well clear them
+ * all.
+ */
+ NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH23_Msk |
+ PPI_CHEN_CH25_Msk;
+
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
if (g_ble_phy_data.phy_encrypted) {
/* RAM representation has S0, LENGTH and S1 fields. (3 bytes) */
@@ -904,15 +1225,12 @@ ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans)
NRF_CCM->EVENTS_ERROR = 0;
NRF_CCM->MODE = CCM_MODE_MODE_Encryption;
NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data;
- NRF_PPI->CHENCLR = PPI_CHEN_CH25_Msk | PPI_CHEN_CH23_Msk;
NRF_PPI->CHENSET = PPI_CHEN_CH24_Msk;
} else {
-
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
/* Reconfigure PCNF0 */
NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) |
(NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos);
- NRF_PPI->CHENCLR = PPI_CHEN_CH23_Msk;
NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0];
#endif
/* RAM representation has S0 and LENGTH fields (2 bytes) */
@@ -927,7 +1245,6 @@ ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans)
/* Reconfigure PCNF0 */
NRF_RADIO->PCNF0 = (NRF_LFLEN_BITS << RADIO_PCNF0_LFLEN_Pos) |
(NRF_S0_LEN << RADIO_PCNF0_S0LEN_Pos);
- NRF_PPI->CHENCLR = PPI_CHEN_CH23_Msk;
#endif
/* RAM representation has S0 and LENGTH fields (2 bytes) */
@@ -1106,29 +1423,62 @@ ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit)
return 0;
}
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
/**
- * Disable the PHY. This will do the following:
- * -> Turn off all phy interrupts.
- * -> Disable internal shortcuts.
- * -> Disable the radio.
- * -> Make sure we wont automatically go to rx/tx on output compare
- * -> Sets phy state to idle.
- * -> Clears any pending irqs in the NVIC. Might not be necessary but we do
- * it as a precaution.
+ * Stop the timer used to count microseconds when using RTC for cputime
*/
void
-ble_phy_disable(void)
+ble_phy_stop_usec_timer(void)
{
- ble_ll_log(BLE_LL_LOG_ID_PHY_DISABLE, g_ble_phy_data.phy_state, 0, 0);
+ NRF_TIMER0->TASKS_STOP = 1;
+ NRF_TIMER0->TASKS_SHUTDOWN = 1;
+ NRF_RTC0->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk;
+}
+#endif
+/**
+ * ble phy disable irq and ppi
+ *
+ * This routine is to be called when reception was stopped due to either a
+ * wait for response timeout or a packet being received and the phy is to be
+ * restarted in receive mode. Generally, the disable routine is called to stop
+ * the phy.
+ */
+void
+ble_phy_disable_irq_and_ppi(void)
+{
NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
NRF_RADIO->SHORTS = 0;
NRF_RADIO->TASKS_DISABLE = 1;
- NRF_PPI->CHENCLR = PPI_CHEN_CH23_Msk | PPI_CHEN_CH21_Msk | PPI_CHEN_CH20_Msk;
+ NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH20_Msk |
+ PPI_CHEN_CH21_Msk | PPI_CHEN_CH23_Msk | PPI_CHEN_CH24_Msk |
+ PPI_CHEN_CH25_Msk | PPI_CHEN_CH31_Msk;
NVIC_ClearPendingIRQ(RADIO_IRQn);
g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
}
+void
+ble_phy_restart_rx(void)
+{
+ ble_phy_disable_irq_and_ppi();
+ ble_phy_rx();
+}
+
+/**
+ * ble phy disable
+ *
+ * Disables the PHY. This should be called when an event is over. It stops
+ * the usec timer (if used), disables interrupts, disables the RADIO, disables
+ * PPI and sets state to idle.
+ */
+void
+ble_phy_disable(void)
+{
+ ble_ll_log(BLE_LL_LOG_ID_PHY_DISABLE, g_ble_phy_data.phy_state, 0, 0);
+ ble_phy_stop_usec_timer();
+ ble_phy_disable_irq_and_ppi();
+}
+
/* Gets the current access address */
uint32_t ble_phy_access_addr_get(void)
{
@@ -1201,3 +1551,17 @@ ble_phy_resolv_list_disable(void)
g_ble_phy_data.phy_privacy = 0;
}
#endif
+
+#ifdef BLE_XCVR_RFCLK
+void
+ble_phy_rfclk_enable(void)
+{
+ NRF_CLOCK->TASKS_HFCLKSTART = 1;
+}
+
+void
+ble_phy_rfclk_disable(void)
+{
+ NRF_CLOCK->TASKS_HFCLKSTOP = 1;
+}
+#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3c785953/hw/drivers/nimble/nrf52/src/ble_phy.c
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/nrf52/src/ble_phy.c b/hw/drivers/nimble/nrf52/src/ble_phy.c
index 8d8b0e1..e6b470e 100644
--- a/hw/drivers/nimble/nrf52/src/ble_phy.c
+++ b/hw/drivers/nimble/nrf52/src/ble_phy.c
@@ -694,6 +694,10 @@ ble_phy_rx_start_isr(void)
usecs = NRF_TIMER0->CC[1] - 40;
ticks = os_cputime_usecs_to_ticks(usecs);
ble_hdr->rem_usecs = usecs - os_cputime_ticks_to_usecs(ticks);
+ if (ble_hdr->rem_usecs == 31) {
+ ble_hdr->rem_usecs = 0;
+ ++ticks;
+ }
ble_hdr->beg_cputime = g_ble_phy_data.phy_start_cputime + ticks;
#else
ble_hdr->beg_cputime = NRF_TIMER0->CC[1] -
@@ -1152,6 +1156,7 @@ ble_phy_rx_set_start_time(void)
} else {
rc = 0;
}
+ return rc;
}
#endif
#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3c785953/kernel/os/src/os_cputime.c
----------------------------------------------------------------------
diff --git a/kernel/os/src/os_cputime.c b/kernel/os/src/os_cputime.c
index 01b15fe..56b626c 100644
--- a/kernel/os/src/os_cputime.c
+++ b/kernel/os/src/os_cputime.c
@@ -122,8 +122,17 @@ os_cputime_usecs_to_ticks(uint32_t usecs)
{
uint64_t ticks;
- ticks = ((uint64_t)usecs << 9) / 15625;
- return (uint32_t)ticks;
+ /*
+ * Faster calculation but could be off 1 full tick since we do not
+ * add residual back. Adding back the residual is commented out below, but
+ * shown.
+ */
+ ticks = (uint64_t)usecs * (uint32_t)((((uint64_t)1 << 32) * 32768) / 1000000);
+
+ /* Residual */
+ //ticks += ((uint64_t)us * (1526122139+1)) >> 32;
+
+ return (uint32_t)(ticks >> 32);
}
/**
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3c785953/net/nimble/controller/include/controller/ble_ll.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll.h b/net/nimble/controller/include/controller/ble_ll.h
index acc201d..2094290 100644
--- a/net/nimble/controller/include/controller/ble_ll.h
+++ b/net/nimble/controller/include/controller/ble_ll.h
@@ -425,7 +425,7 @@ int ble_ll_rand_start(void);
* XXX: temporary LL debug log. Will get removed once we transition to real
* log
*/
-#define BLE_LL_LOG
+#undef BLE_LL_LOG
#include "console/console.h"
#define BLE_LL_LOG_ID_PHY_SETCHAN (1)
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/3c785953/net/nimble/controller/src/ble_ll_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn.c b/net/nimble/controller/src/ble_ll_conn.c
index d7f926e..9a6dc1a 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -242,9 +242,13 @@ ble_ll_conn_calc_itvl_ticks(struct ble_ll_conn_sm *connsm)
*/
usecs = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS;
ticks = os_cputime_usecs_to_ticks(usecs);
- connsm->conn_itvl_ticks = ticks;
connsm->conn_itvl_usecs = (uint8_t)(usecs -
os_cputime_ticks_to_usecs(ticks));
+ if (connsm->conn_itvl_usecs == 31) {
+ connsm->conn_itvl_usecs = 0;
+ ++ticks;
+ }
+ connsm->conn_itvl_ticks = ticks;
}
#endif
[2/5] incubator-mynewt-core git commit: Low power timer. Only nrf52
right now.
Posted by we...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/net/nimble/controller/src/ble_ll_sched.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_sched.c b/net/nimble/controller/src/ble_ll_sched.c
index dd42c3f..ffe8ef3 100644
--- a/net/nimble/controller/src/ble_ll_sched.c
+++ b/net/nimble/controller/src/ble_ll_sched.c
@@ -21,24 +21,35 @@
#include <string.h>
#include "os/os.h"
#include "os/os_cputime.h"
+#include "bsp.h"
#include "ble/xcvr.h"
#include "controller/ble_phy.h"
#include "controller/ble_ll.h"
#include "controller/ble_ll_sched.h"
#include "controller/ble_ll_adv.h"
#include "controller/ble_ll_scan.h"
+#include "controller/ble_ll_xcvr.h"
#include "ble_ll_conn_priv.h"
/* XXX: this is temporary. Not sure what I want to do here */
struct hal_timer g_ble_ll_sched_timer;
+#ifdef BLE_XCVR_RFCLK
+/* Settling time of crystal, in ticks */
+uint8_t g_ble_ll_sched_xtal_ticks;
+#endif
+
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+uint8_t g_ble_ll_sched_offset_ticks;
+#endif
+
#define BLE_LL_SCHED_ADV_WORST_CASE_USECS \
(BLE_LL_SCHED_MAX_ADV_PDU_USECS + BLE_LL_IFS + BLE_LL_SCHED_ADV_MAX_USECS \
+ XCVR_TX_SCHED_DELAY_USECS)
-
#if (BLE_LL_SCHED_DEBUG == 1)
int32_t g_ble_ll_sched_max_late;
+int32_t g_ble_ll_sched_max_early;
#endif
/* XXX: TODO:
@@ -155,6 +166,17 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
/* Get schedule element from connection */
sch = &connsm->conn_sch;
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ /* Set schedule start and end times */
+ sch->start_time = connsm->anchor_point - g_ble_ll_sched_offset_ticks;
+ if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
+ usecs = connsm->slave_cur_window_widening;
+ sch->start_time -= (os_cputime_usecs_to_ticks(usecs) + 1);
+ sch->remainder = 0;
+ } else {
+ sch->remainder = connsm->anchor_point_usecs;
+ }
+#else
/* Set schedule start and end times */
if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
usecs = XCVR_RX_SCHED_DELAY_USECS;
@@ -163,6 +185,7 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
usecs = XCVR_TX_SCHED_DELAY_USECS;
}
sch->start_time = connsm->anchor_point - os_cputime_usecs_to_ticks(usecs);
+#endif
sch->end_time = connsm->ce_end_time;
/* Better be past current time or we just leave */
@@ -236,8 +259,17 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
entry = start_overlap;
}
+#ifdef BLE_XCVR_RFCLK
+ entry = TAILQ_FIRST(&g_ble_ll_sched_q);
+ if (entry == sch) {
+ ble_ll_xcvr_rfclk_timer_start(sch->start_time);
+ } else {
+ sch = entry;
+ }
+#else
/* Get first on list */
sch = TAILQ_FIRST(&g_ble_ll_sched_q);
+#endif
OS_EXIT_CRITICAL(sr);
@@ -247,67 +279,108 @@ ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm *connsm)
return rc;
}
+/**
+ * Called to schedule a connection when the current role is master.
+ *
+ * Context: Interrupt
+ *
+ * @param connsm
+ * @param ble_hdr
+ * @param pyld_len
+ *
+ * @return int
+ */
int
-ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, uint32_t adv_rxend,
- uint8_t req_slots)
+ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
+ struct ble_mbuf_hdr *ble_hdr, uint8_t pyld_len)
{
int rc;
os_sr_t sr;
- uint32_t tps;
+ uint8_t req_slots;
uint32_t initial_start;
uint32_t earliest_start;
uint32_t earliest_end;
uint32_t dur;
uint32_t itvl_t;
- uint32_t ce_end_time;
+ uint32_t adv_rxend;
struct ble_ll_sched_item *entry;
struct ble_ll_sched_item *sch;
- /* Better have a connsm */
- assert(connsm != NULL);
-
/* Get schedule element from connection */
rc = -1;
sch = &connsm->conn_sch;
-
+ req_slots = MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS);
+
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ /* XXX:
+ * The calculations for the 32kHz crystal bear alot of explanation. The
+ * earliest possible time that the master can start the connection with a
+ * slave is 1.25 msecs from the end of the connection request. The
+ * connection request is sent an IFS time from the end of the advertising
+ * packet that was received plus the time it takes to send the connection
+ * request. At 1 Mbps, this is 1752 usecs, or 57.41 ticks. Using 57 ticks
+ * makes us off ~13 usecs. Since we dont want to actually calculate the
+ * receive end time tick (this would take too long), we assume the end of
+ * the advertising PDU is 'now' (we call os_cputime_get32). We dont know
+ * how much time it will take to service the ISR but if we are more than the
+ * rx to tx time of the chip we will not be successful transmitting the
+ * connect request. All this means is that we presume that the slave will
+ * receive the connect request later than we expect but no earlier than
+ * 13 usecs before (this is important).
+ *
+ * The code then attempts to schedule the connection at the
+ * earliest time although this may not be possible. When the actual
+ * schedule start time is determined, the master has to determine if this
+ * time is more than a transmit window offset interval (1.25 msecs). The
+ * master has to tell the slave how many transmit window offsets there are
+ * from the earliest possible time to when the actual transmit start will
+ * occur. Later in this function you will see the calculation. The actual
+ * transmission start has to occur within the transmit window. The transmit
+ * window interval is in units of 1.25 msecs and has to be at least 1. To
+ * make things a bit easier (but less power efficient for the slave), we
+ * use a transmit window of 2. We do this because we dont quite know the
+ * exact start of the transmission and if we are too early or too late we
+ * could miss the transmit window. A final note: the actual transmission
+ * start (the anchor point) is sched offset ticks from the schedule start
+ * time. We dont add this to the calculation when calculating the window
+ * offset. The reason we dont do this is we want to insure we transmit
+ * after the window offset we tell the slave. For example, say we think
+ * we are transmitting 1253 usecs from the earliest start. This would cause
+ * us to send a transmit window offset of 1. Since we are actually
+ * transmitting earlier than the slave thinks we could end up transmitting
+ * before the window offset. Transmitting later is fine since we have the
+ * transmit window to do so. Transmitting before is bad, since the slave
+ * wont be listening. We could do better calculation if we wanted to use
+ * a transmit window of 1 as opposed to 2, but for now we dont care.
+ */
+ dur = req_slots * BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT;
+ adv_rxend = os_cputime_get32();
+ earliest_start = adv_rxend + 57; /* XXX: only works for 1 Mbps */
+ earliest_end = earliest_start + dur;
+ itvl_t = connsm->conn_itvl_ticks;
+#else
+ adv_rxend = ble_hdr->beg_cputime +
+ os_cputime_usecs_to_ticks(BLE_TX_DUR_USECS_M(pyld_len));
/*
* The earliest start time is 1.25 msecs from the end of the connect
* request transmission. Note that adv_rxend is the end of the received
* advertisement, so we need to add an IFS plus the time it takes to send
- * the connection request
+ * the connection request. The 1.25 msecs starts from the end of the conn
+ * request.
*/
dur = os_cputime_usecs_to_ticks(req_slots * BLE_LL_SCHED_USECS_PER_SLOT);
earliest_start = adv_rxend +
os_cputime_usecs_to_ticks(BLE_LL_IFS + BLE_LL_CONN_REQ_DURATION +
BLE_LL_CONN_INITIAL_OFFSET);
earliest_end = earliest_start + dur;
-
itvl_t = os_cputime_usecs_to_ticks(connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS);
+#endif
/* We have to find a place for this schedule */
OS_ENTER_CRITICAL(sr);
/* The schedule item must occur after current running item (if any) */
sch->start_time = earliest_start;
-
- /*
- * If we are currently in a connection, we add one slot time to the
- * earliest start so we can end the connection reasonably.
- */
- if (ble_ll_state_get() == BLE_LL_STATE_CONNECTION) {
- tps = os_cputime_usecs_to_ticks(BLE_LL_SCHED_USECS_PER_SLOT);
- ce_end_time = ble_ll_conn_get_ce_end_time();
- while ((int32_t)(ce_end_time - os_cputime_get32()) < 0) {
- ce_end_time += tps;
- }
-
- /* Start at next slot boundary past earliest */
- while ((int32_t)(ce_end_time - earliest_start) < 0) {
- ce_end_time += tps;
- }
- earliest_start = ce_end_time;
- earliest_end = earliest_start + dur;
- }
initial_start = earliest_start;
if (!ble_ll_sched_insert_if_empty(sch)) {
@@ -338,6 +411,7 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, uint32_t adv_rxend,
}
}
+ /* Must be able to schedule within one connection interval */
if (!entry) {
if ((earliest_start - initial_start) <= itvl_t) {
rc = 0;
@@ -346,18 +420,38 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, uint32_t adv_rxend,
}
if (!rc) {
- /* calculate number of connection intervals before start */
+ /* calculate number of window offsets. Each offset is 1.25 ms */
sch->enqueued = 1;
- connsm->tx_win_off = (earliest_start - initial_start) /
- os_cputime_usecs_to_ticks(BLE_LL_CONN_ITVL_USECS);
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ /*
+ * NOTE: we dont add sched offset ticks as we want to under-estimate
+ * the transmit window slightly since the window size is currently
+ * 2 when using a 32768 crystal.
+ */
+ dur = os_cputime_ticks_to_usecs(earliest_start - initial_start);
+ connsm->tx_win_off = dur / BLE_LL_CONN_TX_OFF_USECS;
+#else
+ dur = os_cputime_ticks_to_usecs(earliest_start - initial_start);
+ dur += XCVR_TX_SCHED_DELAY_USECS;
+ connsm->tx_win_off = dur / BLE_LL_CONN_TX_OFF_USECS;
+#endif
}
}
if (!rc) {
sch->start_time = earliest_start;
sch->end_time = earliest_end;
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ /*
+ * Since we have the transmit window to transmit in, we dont need
+ * to set the anchor point usecs; just transmit to the nearest tick.
+ */
+ connsm->anchor_point = earliest_start + g_ble_ll_sched_offset_ticks;
+ connsm->anchor_point_usecs = 0;
+#else
connsm->anchor_point = earliest_start +
os_cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS);
+#endif
connsm->ce_end_time = earliest_end;
}
@@ -371,6 +465,15 @@ ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, uint32_t adv_rxend,
return rc;
}
+/**
+ * Schedules a slave connection for the first time.
+ *
+ * Context: Link Layer
+ *
+ * @param connsm
+ *
+ * @return int
+ */
int
ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm)
{
@@ -380,15 +483,32 @@ ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm)
struct ble_ll_sched_item *next_sch;
struct ble_ll_sched_item *sch;
+#ifdef BLE_XCVR_RFCLK
+ int first;
+ first = 0;
+#endif
+
/* Get schedule element from connection */
rc = -1;
sch = &connsm->conn_sch;
/* Set schedule start and end times */
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ /*
+ * XXX: for now, we dont care about anchor point usecs for the slave. It
+ * does not matter if we turn on the receiver up to one tick before w
+ * need to. We also subtract one extra tick since the conversion from
+ * usecs to ticks could be off by up to 1 tick.
+ */
+ sch->start_time = connsm->anchor_point - g_ble_ll_sched_offset_ticks -
+ os_cputime_usecs_to_ticks(connsm->slave_cur_window_widening) - 1;
+#else
sch->start_time = connsm->anchor_point -
os_cputime_usecs_to_ticks(XCVR_RX_SCHED_DELAY_USECS +
connsm->slave_cur_window_widening);
+#endif
sch->end_time = connsm->ce_end_time;
+ sch->remainder = 0;
/* We have to find a place for this schedule */
OS_ENTER_CRITICAL(sr);
@@ -403,6 +523,9 @@ ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm)
if (!entry) {
/* Nothing in schedule. Schedule as soon as possible */
rc = 0;
+#ifdef BLE_XCVR_RFCLK
+ first = 1;
+#endif
} else {
os_cputime_timer_stop(&g_ble_ll_sched_timer);
while (1) {
@@ -435,9 +558,24 @@ ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm)
if (!rc) {
sch->enqueued = 1;
}
+#ifdef BLE_XCVR_RFCLK
+ next_sch = TAILQ_FIRST(&g_ble_ll_sched_q);
+ if (next_sch == sch) {
+ first = 1;
+ } else {
+ sch = next_sch;
+ }
+#else
sch = TAILQ_FIRST(&g_ble_ll_sched_q);
+#endif
}
+#ifdef BLE_XCVR_RFCLK
+ if (first) {
+ ble_ll_xcvr_rfclk_timer_start(sch->start_time);
+ }
+#endif
+
OS_EXIT_CRITICAL(sr);
os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time);
@@ -450,9 +588,6 @@ ble_ll_sched_adv_new(struct ble_ll_sched_item *sch)
{
int rc;
os_sr_t sr;
- uint8_t ll_state;
- int32_t ticks;
- uint32_t ce_end_time;
uint32_t adv_start;
uint32_t duration;
struct ble_ll_sched_item *entry;
@@ -463,39 +598,12 @@ ble_ll_sched_adv_new(struct ble_ll_sched_item *sch)
orig = sch;
OS_ENTER_CRITICAL(sr);
-
- /*
- * If we are currently in a connection, we add one slot time to the
- * earliest start so we can end the connection reasonably.
- */
- ll_state = ble_ll_state_get();
- if (ll_state == BLE_LL_STATE_CONNECTION) {
- ticks = (int32_t)os_cputime_usecs_to_ticks(BLE_LL_SCHED_MAX_TXRX_SLOT);
- ce_end_time = ble_ll_conn_get_ce_end_time();
- if ((int32_t)(ce_end_time - sch->start_time) < ticks) {
- ce_end_time += ticks;
- }
- sch->start_time = ce_end_time;
- sch->end_time = ce_end_time + duration;
- }
-#if MYNEWT_VAL(BLE_MULTI_ADV_SUPPORT)
- else if ((ll_state == BLE_LL_STATE_ADV) && (BLE_LL_ADV_INSTANCES > 1)) {
- /*
- * Since we currently dont know how long this item might be scheduled
- * for we add what we think the worst-case time for the advertising
- * scheduled item to be over. We add in a IFS for good measure.
- */
- sch->start_time += BLE_LL_SCHED_MAX_ADV_PDU_USECS + BLE_LL_IFS +
- BLE_LL_SCHED_ADV_MAX_USECS + XCVR_TX_SCHED_DELAY_USECS;
- sch->end_time = sch->start_time + duration;
- }
-#endif
-
entry = ble_ll_sched_insert_if_empty(sch);
if (!entry) {
rc = 0;
adv_start = sch->start_time;
} else {
+ /* XXX: no need to stop timer if not first on list. Modify code? */
os_cputime_timer_stop(&g_ble_ll_sched_timer);
TAILQ_FOREACH(entry, &g_ble_ll_sched_q, link) {
/* We can insert if before entry in list */
@@ -529,13 +637,13 @@ ble_ll_sched_adv_new(struct ble_ll_sched_item *sch)
ble_ll_adv_scheduled((struct ble_ll_adv_sm *)orig->cb_arg, adv_start);
- OS_EXIT_CRITICAL(sr);
+#ifdef BLE_XCVR_RFCLK
+ if (orig == sch) {
+ ble_ll_xcvr_rfclk_timer_start(sch->start_time);
+ }
+#endif
- /* XXX: some things to test. I am not sure that if we are passed the
- output compare that we actually get the interrupt. */
- /* XXX: I am not sure that if we receive a packet while scanning
- * that we actually go back to scanning. I need to make sure
- we re-enable the receive. Put an event in the log! */
+ OS_EXIT_CRITICAL(sr);
os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time);
@@ -653,6 +761,12 @@ ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start,
}
sch->end_time = sch->start_time + duration;
*start = sch->start_time;
+
+#ifdef BLE_XCVR_RFCLK
+ if (sch == TAILQ_FIRST(&g_ble_ll_sched_q)) {
+ ble_ll_xcvr_rfclk_timer_start(sch->start_time);
+ }
+#endif
}
OS_EXIT_CRITICAL(sr);
@@ -784,26 +898,33 @@ ble_ll_sched_execute_item(struct ble_ll_sched_item *sch)
void
ble_ll_sched_run(void *arg)
{
- int32_t dt;
struct ble_ll_sched_item *sch;
/* Look through schedule queue */
- while ((sch = TAILQ_FIRST(&g_ble_ll_sched_q)) != NULL) {
+ sch = TAILQ_FIRST(&g_ble_ll_sched_q);
+ if (sch) {
+#if (BLE_LL_SCHED_DEBUG == 1)
+ int32_t dt;
+
/* Make sure we have passed the start time of the first event */
dt = (int32_t)(os_cputime_get32() - sch->start_time);
- if (dt >= 0) {
-#if (BLE_LL_SCHED_DEBUG == 1)
- if (dt > g_ble_ll_sched_max_late) {
- g_ble_ll_sched_max_late = dt;
- }
+ if (dt > g_ble_ll_sched_max_late) {
+ g_ble_ll_sched_max_late = dt;
+ }
+ if (dt < g_ble_ll_sched_max_early) {
+ g_ble_ll_sched_max_early = dt;
+ }
#endif
- /* Remove schedule item and execute the callback */
- TAILQ_REMOVE(&g_ble_ll_sched_q, sch, link);
- sch->enqueued = 0;
- ble_ll_sched_execute_item(sch);
- } else {
+
+ /* Remove schedule item and execute the callback */
+ TAILQ_REMOVE(&g_ble_ll_sched_q, sch, link);
+ sch->enqueued = 0;
+ ble_ll_sched_execute_item(sch);
+
+ /* Restart if there is an item on the schedule */
+ sch = TAILQ_FIRST(&g_ble_ll_sched_q);
+ if (sch) {
os_cputime_timer_start(&g_ble_ll_sched_timer, sch->start_time);
- break;
}
}
}
@@ -837,6 +958,55 @@ ble_ll_sched_next_time(uint32_t *next_event_time)
return rc;
}
+#ifdef BLE_XCVR_RFCLK
+/**
+ * Checks to see if we need to restart the cputime timer which starts the
+ * rf clock settling.
+ *
+ * NOTE: Should only be called from the Link Layer task!
+ *
+ * Context: Link-Layer task.
+ *
+ */
+void
+ble_ll_sched_rfclk_chk_restart(void)
+{
+ int stop;
+ os_sr_t sr;
+ uint8_t ll_state;
+ int32_t time_till_next;
+ uint32_t next_time;
+
+ stop = 0;
+ OS_ENTER_CRITICAL(sr);
+ ll_state = ble_ll_state_get();
+ if (ble_ll_sched_next_time(&next_time)) {
+ /*
+ * If the time until the next event is too close, no need to start
+ * the timer. Leave clock on.
+ */
+ time_till_next = (int32_t)(next_time - os_cputime_get32());
+ if (time_till_next > g_ble_ll_data.ll_xtal_ticks) {
+ /* Stop the clock */
+ stop = 1;
+ ble_ll_xcvr_rfclk_timer_start(next_time);
+ }
+ } else {
+ stop = 1;
+ }
+
+ /* Only disable the rfclk if doing nothing */
+ if (stop && (ll_state == BLE_LL_STATE_STANDBY)) {
+ ble_ll_log(BLE_LL_LOG_ID_RFCLK_SCHED_DIS, g_ble_ll_data.ll_rfclk_state,
+ 0, 0);
+ ble_ll_xcvr_rfclk_disable();
+ }
+ OS_EXIT_CRITICAL(sr);
+}
+
+#endif
+
+
/**
* Stop the scheduler
*
@@ -857,6 +1027,24 @@ ble_ll_sched_stop(void)
int
ble_ll_sched_init(void)
{
+ /*
+ * Initialize max early to large negative number. This is used
+ * to determine the worst-case "early" time the schedule was called. Dont
+ * expect this to be less than -3 or -4.
+ */
+#if (BLE_LL_SCHED_DEBUG == 1)
+ g_ble_ll_sched_max_early = -50000;
+#endif
+
+ /*
+ * This is the offset from the start of the scheduled item until the actual
+ * tx/rx should occur, in ticks. We also "round up" to the nearest tick.
+ */
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ g_ble_ll_sched_offset_ticks =
+ os_cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS + 30);
+#endif
+
/* Initialize cputimer for the scheduler */
os_cputime_timer_init(&g_ble_ll_sched_timer, ble_ll_sched_run, NULL);
return 0;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/net/nimble/controller/src/ble_ll_xcvr.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_xcvr.c b/net/nimble/controller/src/ble_ll_xcvr.c
new file mode 100644
index 0000000..50ab32e
--- /dev/null
+++ b/net/nimble/controller/src/ble_ll_xcvr.c
@@ -0,0 +1,153 @@
+/*
+ * 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 "syscfg/syscfg.h"
+#include "os/os_cputime.h"
+#include "controller/ble_phy.h"
+#include "controller/ble_ll.h"
+#include "controller/ble_ll_xcvr.h"
+
+#ifdef BLE_XCVR_RFCLK
+int
+ble_ll_xcvr_rfclk_state(void)
+{
+ uint32_t expiry;
+
+ if (g_ble_ll_data.ll_rfclk_state == BLE_RFCLK_STATE_ON) {
+ expiry = g_ble_ll_data.ll_rfclk_start_time;
+ if ((int32_t)(os_cputime_get32() - expiry) >
+ g_ble_ll_data.ll_xtal_ticks) {
+ g_ble_ll_data.ll_rfclk_state = BLE_RFCLK_STATE_SETTLED;
+ }
+ }
+ return g_ble_ll_data.ll_rfclk_state;
+}
+
+void
+ble_ll_xcvr_rfclk_enable(void)
+{
+ g_ble_ll_data.ll_rfclk_state = BLE_RFCLK_STATE_ON;
+ ble_phy_rfclk_enable();
+}
+
+void
+ble_ll_xcvr_rfclk_disable(void)
+{
+ ble_phy_rfclk_disable();
+ g_ble_ll_data.ll_rfclk_state = BLE_RFCLK_STATE_OFF;
+}
+
+void
+ble_ll_xcvr_rfclk_stop(void)
+{
+ ble_ll_log(BLE_LL_LOG_ID_RFCLK_STOP, g_ble_ll_data.ll_rfclk_state, 0,0);
+ os_cputime_timer_stop(&g_ble_ll_data.ll_rfclk_timer);
+ ble_ll_xcvr_rfclk_disable();
+}
+
+uint32_t
+ble_ll_xcvr_rfclk_time_till_settled(void)
+{
+ int32_t dt;
+ uint32_t rc;
+
+ rc = 0;
+ if (g_ble_ll_data.ll_rfclk_state == BLE_RFCLK_STATE_ON) {
+ dt = (int32_t)(os_cputime_get32() - g_ble_ll_data.ll_rfclk_start_time);
+ assert(dt >= 0);
+ if (dt < g_ble_ll_data.ll_xtal_ticks) {
+ rc = g_ble_ll_data.ll_xtal_ticks - (uint32_t)dt;
+ }
+ }
+
+ return rc;
+}
+
+/**
+ * Called when the timer to turn on the RF CLOCK expires. This function checks
+ * the state of the clock. If the clock is off, the clock is turned on.
+ * Otherwise, we just exit.
+ *
+ * Context: Interrupt
+ *
+ * @param arg
+ */
+void
+ble_ll_xcvr_rfclk_timer_exp(void *arg)
+{
+ if (g_ble_ll_data.ll_rfclk_state == BLE_RFCLK_STATE_OFF) {
+ ble_ll_xcvr_rfclk_start_now(os_cputime_get32());
+ }
+}
+
+/**
+ * This API is used to turn on the rfclock without setting the cputime timer to
+ * start the clock at some later point.
+ *
+ * NOTE: presumes that the state of the rf clock was checked prior to calling.
+ *
+ * @param now
+ */
+void
+ble_ll_xcvr_rfclk_start_now(uint32_t now)
+{
+ ble_ll_xcvr_rfclk_enable();
+ g_ble_ll_data.ll_rfclk_start_time = now;
+ ble_ll_log(BLE_LL_LOG_ID_RFCLK_ENABLE, 0, 0, now);
+}
+
+/**
+ * Starts the timer that will turn the rf clock on. The 'cputime' is
+ * the time at which the clock needs to be settled.
+ *
+ * @param cputime Time at which rfclock should be on and settled.
+ */
+void
+ble_ll_xcvr_rfclk_timer_start(uint32_t cputime)
+{
+ /*
+ * If we are currently in an advertising event or a connection event,
+ * no need to start the cputime timer
+ */
+ if ((g_ble_ll_data.ll_state == BLE_LL_STATE_ADV) ||
+ (g_ble_ll_data.ll_state == BLE_LL_STATE_CONNECTION)) {
+ return;
+ }
+
+ /* Account for the settling time */
+ cputime -= g_ble_ll_data.ll_xtal_ticks;
+
+ /*
+ * If the timer is on the list, we need to see if its expiry is before
+ * 'cputime'. If the expiry is before, no need to do anything. If it
+ * is after, we need to stop the timer and start at new time.
+ */
+ if (g_ble_ll_data.ll_rfclk_timer.link.tqe_prev != NULL) {
+ if ((int32_t)(cputime - g_ble_ll_data.ll_rfclk_timer.expiry) >= 0) {
+ return;
+ }
+ os_cputime_timer_stop(&g_ble_ll_data.ll_rfclk_timer);
+ }
+ os_cputime_timer_start(&g_ble_ll_data.ll_rfclk_timer, cputime);
+ ble_ll_log(BLE_LL_LOG_ID_RFCLK_START, g_ble_ll_data.ll_rfclk_state, 0,
+ g_ble_ll_data.ll_rfclk_timer.expiry);
+}
+#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/net/nimble/controller/syscfg.yml
----------------------------------------------------------------------
diff --git a/net/nimble/controller/syscfg.yml b/net/nimble/controller/syscfg.yml
index 357decc..569010f 100644
--- a/net/nimble/controller/syscfg.yml
+++ b/net/nimble/controller/syscfg.yml
@@ -137,6 +137,14 @@ syscfg.defs:
material often.
value: '32'
+ # Crystal setting time
+ BLE_XTAL_SETTLE_TIME:
+ description: >
+ The settling time of the high-frequency oscillator. This is
+ used to turn on/off the clock used for the radio (assuming
+ the HW supports this). This value is in microseconds.
+ value: '0'
+
# Configuration for LL supported features.
#
# There are a total 8 features that the LL can support. These can be found
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/net/nimble/host/src/ble_hs_hci_evt.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_hci_evt.c b/net/nimble/host/src/ble_hs_hci_evt.c
index cd98f7f..a9655e3 100644
--- a/net/nimble/host/src/ble_hs_hci_evt.c
+++ b/net/nimble/host/src/ble_hs_hci_evt.c
@@ -6,7 +6,7 @@
* 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,
@@ -624,8 +624,8 @@ ble_hs_hci_evt_acl_process(struct os_mbuf *om)
#if (BLETEST_THROUGHPUT_TEST == 0)
BLE_HS_LOG(DEBUG, "ble_hs_hci_evt_acl_process(): conn_handle=%u pb=%x "
"len=%u data=",
- BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc),
- BLE_HCI_DATA_PB(hci_hdr.hdh_handle_pb_bc),
+ BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc),
+ BLE_HCI_DATA_PB(hci_hdr.hdh_handle_pb_bc),
hci_hdr.hdh_len);
ble_hs_log_mbuf(om);
BLE_HS_LOG(DEBUG, "\n");
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/net/nimble/include/nimble/ble.h
----------------------------------------------------------------------
diff --git a/net/nimble/include/nimble/ble.h b/net/nimble/include/nimble/ble.h
index b514131..6f29fd4 100644
--- a/net/nimble/include/nimble/ble.h
+++ b/net/nimble/include/nimble/ble.h
@@ -96,6 +96,9 @@ struct ble_mbuf_hdr
struct ble_mbuf_hdr_txinfo txinfo;
};
uint32_t beg_cputime;
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
+ uint32_t rem_usecs;
+#endif
};
#define BLE_MBUF_HDR_CRC_OK(hdr) \
[3/5] incubator-mynewt-core git commit: Low power timer. Only nrf52
right now.
Posted by we...@apache.org.
Low power timer. Only nrf52 right now.
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/507f493a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/507f493a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/507f493a
Branch: refs/heads/develop
Commit: 507f493ab86266528c7f921784978e63a07ddd33
Parents: 8158805
Author: William San Filippo <wi...@runtime.io>
Authored: Thu Feb 16 16:12:39 2017 -0800
Committer: William San Filippo <wi...@runtime.io>
Committed: Thu Mar 30 14:09:52 2017 -0700
----------------------------------------------------------------------
apps/bletest/src/main.c | 2 +-
hw/drivers/nimble/nrf52/include/ble/xcvr.h | 12 +-
hw/drivers/nimble/nrf52/src/ble_phy.c | 438 +++++++++++++++++--
kernel/os/include/os/os_cputime.h | 8 +
kernel/os/src/os_cputime.c | 50 +++
.../controller/include/controller/ble_ll.h | 51 ++-
.../controller/include/controller/ble_ll_conn.h | 5 +
.../include/controller/ble_ll_sched.h | 32 +-
.../controller/include/controller/ble_ll_xcvr.h | 48 ++
.../controller/include/controller/ble_phy.h | 31 +-
net/nimble/controller/src/ble_ll.c | 37 ++
net/nimble/controller/src/ble_ll_adv.c | 86 +++-
net/nimble/controller/src/ble_ll_conn.c | 265 +++++++++--
net/nimble/controller/src/ble_ll_conn_priv.h | 3 +-
net/nimble/controller/src/ble_ll_scan.c | 145 +++++-
net/nimble/controller/src/ble_ll_sched.c | 354 +++++++++++----
net/nimble/controller/src/ble_ll_xcvr.c | 153 +++++++
net/nimble/controller/syscfg.yml | 8 +
net/nimble/host/src/ble_hs_hci_evt.c | 6 +-
net/nimble/include/nimble/ble.h | 3 +
20 files changed, 1531 insertions(+), 206 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/apps/bletest/src/main.c
----------------------------------------------------------------------
diff --git a/apps/bletest/src/main.c b/apps/bletest/src/main.c
index e2519eb..efb3fd4 100755
--- a/apps/bletest/src/main.c
+++ b/apps/bletest/src/main.c
@@ -172,7 +172,7 @@ bletest_multi_adv_instances[BLETEST_CFG_ADV_TEST_INSTANCES] = {
#define BLETEST_CFG_MAX_CE_LEN (BLETEST_CFG_CONN_ITVL)
#define BLETEST_CFG_CONN_PEER_ADDR_TYPE (BLE_HCI_CONN_PEER_ADDR_PUBLIC)
#define BLETEST_CFG_CONN_OWN_ADDR_TYPE (BLE_HCI_ADV_OWN_ADDR_PUBLIC)
-#define BLETEST_CFG_CONCURRENT_CONNS (1)
+#define BLETEST_CFG_CONCURRENT_CONNS (8)
/* Test packet config */
#define BLETEST_CFG_RAND_PKT_SIZE (1)
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/hw/drivers/nimble/nrf52/include/ble/xcvr.h
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/nrf52/include/ble/xcvr.h b/hw/drivers/nimble/nrf52/include/ble/xcvr.h
index 6a35124..2b6d7ea 100644
--- a/hw/drivers/nimble/nrf52/include/ble/xcvr.h
+++ b/hw/drivers/nimble/nrf52/include/ble/xcvr.h
@@ -24,10 +24,18 @@
extern "C" {
#endif
-/* Transceiver specific definitions */
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+/*
+ * NOTE: we have to account for the RTC output compare issue, which is why
+ * this number is much larger when using the 32.768 crystal for cputime. We
+ * want it to be 5 ticks.
+ */
+#define XCVR_PROC_DELAY_USECS (153)
+#else
+#define XCVR_PROC_DELAY_USECS (50)
+#endif
#define XCVR_RX_START_DELAY_USECS (140)
#define XCVR_TX_START_DELAY_USECS (140)
-#define XCVR_PROC_DELAY_USECS (50)
#define XCVR_TX_SCHED_DELAY_USECS \
(XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
#define XCVR_RX_SCHED_DELAY_USECS \
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/hw/drivers/nimble/nrf52/src/ble_phy.c
----------------------------------------------------------------------
diff --git a/hw/drivers/nimble/nrf52/src/ble_phy.c b/hw/drivers/nimble/nrf52/src/ble_phy.c
index 8771f49..8d8b0e1 100644
--- a/hw/drivers/nimble/nrf52/src/ble_phy.c
+++ b/hw/drivers/nimble/nrf52/src/ble_phy.c
@@ -78,6 +78,9 @@ struct ble_phy_obj
struct ble_mbuf_hdr rxhdr;
void *txend_arg;
ble_phy_tx_end_func txend_cb;
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ uint32_t phy_start_cputime;
+#endif
};
struct ble_phy_obj g_ble_phy_data;
@@ -280,6 +283,133 @@ nrf_wait_disabled(void)
}
}
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+/**
+ *
+ *
+ */
+int
+ble_phy_set_start_time(uint32_t cputime, uint8_t rem_usecs)
+{
+ uint32_t next_cc;
+ uint32_t cur_cc;
+ uint32_t cntr;
+ uint32_t delta;
+
+ /*
+ * XXX: The TXEN time is 140 usecs but there may be additional delays
+ * Need to look at this.
+ */
+
+ /*
+ * With the 32.768 kHz crystal, we may need to adjust the RTC compare
+ * value by 1 tick due to the time it takes for TXEN. The code uses a 5 RTC
+ * tick offset, which is 152.5 usecs. The TXEN time is 140 usecs. This
+ * means that with a remainder of 0, TIMER0 should be set to 12 or 13 (as
+ * TIMER0 counts at 1MHz). A remainder of 19 or more we will need to add
+ * 1 tick. We dont need to add 1 tick per se, but it does give us slightly
+ * more time and thus less of a chance to miss a tick. Another note: we
+ * cant set TIMER0 CC to 0 as the compare wont occur; it must be 1 or more.
+ * This is why we subtract 18 (as opposed to 19) as rem_uses will be >= 1.
+ */
+ if (rem_usecs <= 18) {
+ cputime -= 5;
+ rem_usecs += 12;
+ } else {
+ cputime -= 4;
+ rem_usecs -= 18;
+ }
+
+ /*
+ * Can we set the RTC compare to start TIMER0? We can do it if:
+ * a) Current compare value is not N+1 or N+2 ticks from current
+ * counter.
+ * b) The value we want to set is not at least N+2 from current
+ * counter.
+ *
+ * NOTE: since the counter can tick 1 while we do these calculations we
+ * need to account for it.
+ */
+ next_cc = cputime & 0xffffff;
+ cur_cc = NRF_RTC0->CC[0];
+ cntr = NRF_RTC0->COUNTER;
+
+ delta = (cur_cc - cntr) & 0xffffff;
+ if ((delta <= 3) && (delta != 0)) {
+ return -1;
+ }
+ delta = (next_cc - cntr) & 0xffffff;
+ if ((delta & 0x800000) || (delta < 3)) {
+ return -1;
+ }
+
+ /* Clear and set TIMER0 to fire off at proper time */
+ NRF_TIMER0->TASKS_CLEAR = 1;
+ NRF_TIMER0->CC[0] = rem_usecs;
+ NRF_TIMER0->EVENTS_COMPARE[0] = 0;
+
+ /* Set RTC compare to start TIMER0 */
+ NRF_RTC0->EVENTS_COMPARE[0] = 0;
+ NRF_RTC0->CC[0] = next_cc;
+ NRF_RTC0->EVTENSET = RTC_EVTENSET_COMPARE0_Msk;
+
+ /* Enable PPI */
+ NRF_PPI->CHENSET = PPI_CHEN_CH31_Msk;
+
+ /* Store the cputime at which we set the RTC */
+ g_ble_phy_data.phy_start_cputime = cputime;
+
+ return 0;
+}
+
+/**
+ * Function is used to set PPI so that we can time out waiting for a reception
+ * to occur. This happens for two reasons: we have sent a packet and we are
+ * waiting for a respons (txrx should be set to ENABLE_TXRX) or we are
+ * starting a connection event and we are a slave and we are waiting for the
+ * master to send us a packet (txrx should be set to ENABLE_RX).
+ *
+ * NOTE: when waiting for a txrx turn-around, wfr_usecs is not used as there
+ * is no additional time to wait; we know when we should receive the address of
+ * the received frame.
+ *
+ * @param txrx Flag denoting if this wfr is a txrx turn-around or not.
+ * @param wfr_usecs Amount of usecs to wait.
+ */
+void
+ble_phy_wfr_enable(int txrx, uint32_t wfr_usecs)
+{
+ uint32_t end_time;
+
+ if (txrx == BLE_PHY_WFR_ENABLE_TXRX) {
+ /*
+ * Timeout occurs an IFS time plus time it takes to receive address
+ * from the transmit end. We add additional time to make sure the
+ * address event comes before the compare. Note that transmit end
+ * is captured in CC[2]
+ *
+ * XXX: this assumes 1Mbps as 40 usecs is header rx time for 1Mbps
+ */
+ end_time = NRF_TIMER0->CC[2] + BLE_LL_IFS + 40 + 16;
+ } else {
+ /* CC[0] is set to when RXEN occurs. NOTE: the extra 16 usecs is
+ jitter */
+ end_time = NRF_TIMER0->CC[0] + XCVR_RX_START_DELAY_USECS + wfr_usecs +
+ 40 + 16;
+ }
+
+ /* wfr_secs is the time from rxen until timeout */
+ NRF_TIMER0->CC[3] = end_time;
+ NRF_TIMER0->EVENTS_COMPARE[3] = 0;
+
+ /* Enable wait for response PPI */
+ NRF_PPI->CHENSET = (PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk);
+
+ /* Enable the disabled interrupt so we time out on events compare */
+ NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk;
+}
+#endif
+
/**
* Setup transceiver for receive.
*/
@@ -360,14 +490,18 @@ ble_phy_tx_end_isr(void)
uint8_t transition;
uint8_t txlen;
uint32_t wfr_time;
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) != 32768)
uint32_t txstart;
+#endif
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) != 32768)
/*
* Read captured tx start time. This is not the actual transmit start
* time but it is the time at which the address event occurred
* (after transmission of access address)
*/
txstart = NRF_TIMER0->CC[1];
+#endif
/* If this transmission was encrypted we need to remember it */
was_encrypted = g_ble_phy_data.phy_encrypted;
@@ -376,14 +510,20 @@ ble_phy_tx_end_isr(void)
assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX);
/* Log the event */
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
+ ble_ll_log(BLE_LL_LOG_ID_PHY_TXEND, g_ble_phy_data.phy_tx_pyld_len,
+ was_encrypted, NRF_TIMER0->CC[2]);
+#else
ble_ll_log(BLE_LL_LOG_ID_PHY_TXEND, g_ble_phy_data.phy_tx_pyld_len,
was_encrypted, txstart);
+#endif
/* Clear events and clear interrupt on disabled event */
NRF_RADIO->EVENTS_DISABLED = 0;
NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk;
NRF_RADIO->EVENTS_END = 0;
wfr_time = NRF_RADIO->SHORTS;
+ (void)wfr_time;
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
/*
@@ -416,13 +556,28 @@ ble_phy_tx_end_isr(void)
if (txlen && was_encrypted) {
txlen += BLE_LL_DATA_MIC_LEN;
}
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
+ ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_TXRX, 0);
+#else
wfr_time = BLE_LL_WFR_USECS - BLE_TX_LEN_USECS_M(NRF_RX_START_OFFSET);
wfr_time += BLE_TX_DUR_USECS_M(txlen);
wfr_time = os_cputime_usecs_to_ticks(wfr_time);
ble_ll_wfr_enable(txstart + wfr_time);
+#endif
} else {
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
+ /*
+ * XXX: not sure we need to stop the timer here all the time. Or that
+ * it should be stopped here.
+ */
+ NRF_TIMER0->TASKS_STOP = 1;
+ NRF_TIMER0->TASKS_SHUTDOWN = 1;
+ NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk |
+ PPI_CHEN_CH20_Msk | PPI_CHEN_CH31_Msk;
+#else
/* Disable automatic TXEN */
NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk;
+#endif
assert(transition == BLE_PHY_TRANSITION_NONE);
}
}
@@ -506,12 +661,48 @@ ble_phy_rx_start_isr(void)
{
int rc;
uint32_t state;
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ uint32_t usecs;
+ uint32_t ticks;
+#endif
struct ble_mbuf_hdr *ble_hdr;
/* Clear events and clear interrupt */
NRF_RADIO->EVENTS_ADDRESS = 0;
+
+ /* Clear wfr timer channels and DISABLED interrupt */
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk | RADIO_INTENCLR_ADDRESS_Msk;
+ NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk;
+#else
NRF_RADIO->INTENCLR = RADIO_INTENCLR_ADDRESS_Msk;
+#endif
+ /* Initialize the ble mbuf header */
+ ble_hdr = &g_ble_phy_data.rxhdr;
+ ble_hdr->rxinfo.flags = ble_ll_state_get();
+ ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan;
+ ble_hdr->rxinfo.handle = 0;
+
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
+ /*
+ * Calculate receive start time. We assume that the header time is
+ * 40 usecs (only 1 mbps supported right now).
+ *
+ * XXX: possibly use other routine with remainder!
+ */
+ usecs = NRF_TIMER0->CC[1] - 40;
+ ticks = os_cputime_usecs_to_ticks(usecs);
+ ble_hdr->rem_usecs = usecs - os_cputime_ticks_to_usecs(ticks);
+ ble_hdr->beg_cputime = g_ble_phy_data.phy_start_cputime + ticks;
+#else
+ ble_hdr->beg_cputime = NRF_TIMER0->CC[1] -
+ os_cputime_usecs_to_ticks(BLE_TX_LEN_USECS_M(NRF_RX_START_OFFSET));
+#endif
+
+ /* XXX: I wonder if we always have the 1st byte. If we need to wait for
+ * rx chain delay, it could be 18 usecs from address interrupt. The
+ nrf52 may be able to get here early. */
/* Wait to get 1st byte of frame */
while (1) {
state = NRF_RADIO->STATE;
@@ -530,14 +721,6 @@ ble_phy_rx_start_isr(void)
}
}
- /* Initialize flags, channel and state in ble header at rx start */
- ble_hdr = &g_ble_phy_data.rxhdr;
- ble_hdr->rxinfo.flags = ble_ll_state_get();
- ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan;
- ble_hdr->rxinfo.handle = 0;
- ble_hdr->beg_cputime = NRF_TIMER0->CC[1] -
- os_cputime_usecs_to_ticks(BLE_TX_LEN_USECS_M(NRF_RX_START_OFFSET));
-
/* Call Link Layer receive start function */
rc = ble_ll_rx_start((uint8_t *)&g_ble_phy_rx_buf[0] + 3,
g_ble_phy_data.phy_chan,
@@ -573,16 +756,34 @@ ble_phy_isr(void)
/* Read irq register to determine which interrupts are enabled */
irq_en = NRF_RADIO->INTENCLR;
- /* Check for disabled event. This only happens for transmits now */
- if ((irq_en & RADIO_INTENCLR_DISABLED_Msk) && NRF_RADIO->EVENTS_DISABLED) {
- ble_phy_tx_end_isr();
- }
+ /*
+ * NOTE: order of checking is important! Possible, if things get delayed,
+ * we have both an ADDRESS and DISABLED interrupt in rx state. If we get
+ * an address, we disable the DISABLED interrupt.
+ */
/* We get this if we have started to receive a frame */
if ((irq_en & RADIO_INTENCLR_ADDRESS_Msk) && NRF_RADIO->EVENTS_ADDRESS) {
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ irq_en &= ~RADIO_INTENCLR_DISABLED_Msk;
+#endif
ble_phy_rx_start_isr();
}
+ /* Check for disabled event. This only happens for transmits now */
+ if ((irq_en & RADIO_INTENCLR_DISABLED_Msk) && NRF_RADIO->EVENTS_DISABLED) {
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ if (g_ble_phy_data.phy_state == BLE_PHY_STATE_RX) {
+ NRF_RADIO->EVENTS_DISABLED = 0;
+ ble_ll_wfr_timer_exp(NULL);
+ } else {
+ ble_phy_tx_end_isr();
+ }
+#else
+ ble_phy_tx_end_isr();
+#endif
+ }
+
/* Receive packet end (we dont enable this for transmit) */
if ((irq_en & RADIO_INTENCLR_END_Msk) && NRF_RADIO->EVENTS_END) {
ble_phy_rx_end_isr();
@@ -606,6 +807,8 @@ int
ble_phy_init(void)
{
int rc;
+
+#if !defined(BLE_XCVR_RFCLK)
uint32_t os_tmo;
/* Make sure HFXO is started */
@@ -620,6 +823,7 @@ ble_phy_init(void)
return BLE_PHY_ERR_INIT;
}
}
+#endif
/* Set phy channel to an invalid channel so first set channel works */
g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS;
@@ -657,8 +861,13 @@ ble_phy_init(void)
/* Configure IFS */
NRF_RADIO->TIFS = BLE_LL_IFS;
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ /* Captures tx/rx start in timer0 cc 1 and tx/rx end in timer0 cc 2 */
+ NRF_PPI->CHENSET = PPI_CHEN_CH26_Msk | PPI_CHEN_CH27_Msk;
+#else
/* Captures tx/rx start in timer0 capture 1 */
NRF_PPI->CHENSET = PPI_CHEN_CH26_Msk;
+#endif
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
NRF_CCM->INTENCLR = 0xffffffff;
@@ -677,6 +886,27 @@ ble_phy_init(void)
NRF_AAR->NIRK = 0;
#endif
+ /* TIMER0 setup for PHY when using RTC */
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
+ NRF_TIMER0->TASKS_STOP = 1;
+ NRF_TIMER0->TASKS_SHUTDOWN = 1;
+ NRF_TIMER0->BITMODE = 3; /* 32-bit timer */
+ NRF_TIMER0->MODE = 0; /* Timer mode */
+ NRF_TIMER0->PRESCALER = 4; /* gives us 1 MHz */
+
+ /*
+ * PPI setup.
+ * Channel 4: Captures TIMER0 in CC[3] when EVENTS_ADDRESS occurs. Used
+ * to cancel the wait for response timer.
+ * Channel 5: TIMER0 CC[3] to TASKS_DISABLE on radio. This is the wait
+ * for response timer.
+ */
+ NRF_PPI->CH[4].EEP = (uint32_t)&(NRF_RADIO->EVENTS_ADDRESS);
+ NRF_PPI->CH[4].TEP = (uint32_t)&(NRF_TIMER0->TASKS_CAPTURE[3]);
+ NRF_PPI->CH[5].EEP = (uint32_t)&(NRF_TIMER0->EVENTS_COMPARE[3]);
+ NRF_PPI->CH[5].TEP = (uint32_t)&(NRF_RADIO->TASKS_DISABLE);
+#endif
+
/* Set isr in vector table and enable interrupt */
NVIC_SetPriority(RADIO_IRQn, 0);
NVIC_SetVector(RADIO_IRQn, (uint32_t)ble_phy_isr);
@@ -785,6 +1015,7 @@ ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg)
g_ble_phy_data.txend_arg = arg;
}
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
/**
* Called to set the start time of a transmission.
*
@@ -794,28 +1025,38 @@ ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg)
* NOTE: care must be taken when calling this function. The channel should
* already be set.
*
- * @param cputime
- *
+ * @param cputime This is the tick at which the 1st bit of the preamble
+ * should be transmitted
+ * @param rem_usecs This is used only when the underlying timing uses a 32.768
+ * kHz crystal. It is the # of usecs from the cputime tick
+ * at which the first bit of the preamble should be
+ * transmitted.
* @return int
*/
int
-ble_phy_tx_set_start_time(uint32_t cputime)
+ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
{
int rc;
- NRF_TIMER0->CC[0] = cputime;
- NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk;
+ /* XXX: This should not be necessary, but paranoia is good! */
+ /* Clear timer0 compare to RXEN since we are transmitting */
NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
- if ((int32_t)(os_cputime_get32() - cputime) >= 0) {
+
+ /*
+ * XXX: The TXEN time is 140 usecs but there may be additional delays
+ * Need to look at this.
+ */
+ if (ble_phy_set_start_time(cputime, rem_usecs) != 0) {
STATS_INC(ble_phy_stats, tx_late);
ble_phy_disable();
- rc = BLE_PHY_ERR_TX_LATE;
+ rc = BLE_PHY_ERR_TX_LATE;
} else {
+ /* Enable PPI to automatically start TXEN */
+ NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk;
rc = 0;
}
return rc;
}
-
/**
* Called to set the start time of a reception
*
@@ -830,23 +1071,90 @@ ble_phy_tx_set_start_time(uint32_t cputime)
* @return int
*/
int
-ble_phy_rx_set_start_time(uint32_t cputime)
+ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs)
{
int rc;
+ /* XXX: This should not be necessary, but paranoia is good! */
+ /* Clear timer0 compare to TXEN since we are transmitting */
+ NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk;
+
+ /*
+ * XXX: The RXEN time is 138 usecs but there may be additional delays
+ * Need to look at this.
+ */
+ if (ble_phy_set_start_time(cputime, rem_usecs) != 0) {
+ STATS_INC(ble_phy_stats, rx_late);
+ NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
+ NRF_RADIO->TASKS_RXEN = 1;
+ rc = BLE_PHY_ERR_RX_LATE;
+ } else {
+ /* Enable PPI to automatically start RXEN */
+ NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk;
+
+ /* Start rx */
+ rc = ble_phy_rx();
+ }
+ return rc;
+}
+#else
+/**
+ * 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 This is the tick at which the 1st bit of the preamble
+ * should be transmitted
+ * @return int
+ */
+int
+ble_phy_tx_set_start_time(uint32_t cputime)
+{
+ int rc;
+
+ cputime -= os_cputime_usecs_to_ticks(XCVR_TX_START_DELAY_USECS);
+ NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
NRF_TIMER0->CC[0] = cputime;
+ NRF_TIMER0->EVENTS_COMPARE[0] = 0;
+ NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk;
+ if ((int32_t)(os_cputime_get32() - cputime) >= 0) {
+ STATS_INC(ble_phy_stats, tx_late);
+ ble_phy_disable();
+ rc = BLE_PHY_ERR_TX_LATE;
+ } else {
+ rc = 0;
+ }
+
+ return rc;
+}
+
+#if 0
+int
+ble_phy_rx_set_start_time(void)
+{
+ /*
+ * XXX: For now, we dont use this function if we are not using the
+ * RTC. Keeping the code around just in case we want to use it later.
+ */
NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk;
+ NRF_TIMER0->CC[0] = cputime;
+ NRF_TIMER0->EVENTS_COMPARE[0] = 0;
NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk;
if ((int32_t)(os_cputime_get32() - cputime) >= 0) {
STATS_INC(ble_phy_stats, rx_late);
NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
NRF_RADIO->TASKS_RXEN = 1;
- rc = BLE_PHY_ERR_TX_LATE;
+ rc = BLE_PHY_ERR_RX_LATE;
} else {
rc = 0;
}
- return rc;
}
+#endif
+#endif
int
ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans)
@@ -871,6 +1179,16 @@ ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans)
ble_hdr = BLE_MBUF_HDR_PTR(txpdu);
payload_len = ble_hdr->txinfo.pyld_len;
+ /*
+ * XXX: Although we may not have to do this here, I clear all the PPI
+ * that should not be used when transmitting. Some of them are only enabled
+ * if encryption and/or privacy is on, but I dont care. Better to be
+ * paranoid, and if you are going to clear one, might as well clear them
+ * all.
+ */
+ NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH23_Msk |
+ PPI_CHEN_CH25_Msk;
+
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1)
if (g_ble_phy_data.phy_encrypted) {
dptr = (uint8_t *)&g_ble_phy_enc_buf[0];
@@ -883,11 +1201,9 @@ ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans)
NRF_CCM->EVENTS_ERROR = 0;
NRF_CCM->MODE = CCM_MODE_LENGTH_Msk;
NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data;
- NRF_PPI->CHENCLR = PPI_CHEN_CH25_Msk | PPI_CHEN_CH23_Msk;
NRF_PPI->CHENSET = PPI_CHEN_CH24_Msk;
} else {
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
- NRF_PPI->CHENCLR = PPI_CHEN_CH23_Msk;
NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0];
#endif
dptr = (uint8_t *)&g_ble_phy_tx_buf[0];
@@ -895,9 +1211,6 @@ ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans)
pktptr = dptr;
}
#else
-#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
- NRF_PPI->CHENCLR = PPI_CHEN_CH23_Msk;
-#endif
dptr = (uint8_t *)&g_ble_phy_tx_buf[0];
++dptr;
pktptr = dptr;
@@ -1077,29 +1390,62 @@ ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit)
return 0;
}
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
/**
- * Disable the PHY. This will do the following:
- * -> Turn off all phy interrupts.
- * -> Disable internal shortcuts.
- * -> Disable the radio.
- * -> Make sure we wont automatically go to rx/tx on output compare
- * -> Sets phy state to idle.
- * -> Clears any pending irqs in the NVIC. Might not be necessary but we do
- * it as a precaution.
+ * Stop the timer used to count microseconds when using RTC for cputime
*/
void
-ble_phy_disable(void)
+ble_phy_stop_usec_timer(void)
{
- ble_ll_log(BLE_LL_LOG_ID_PHY_DISABLE, g_ble_phy_data.phy_state, 0, 0);
+ NRF_TIMER0->TASKS_STOP = 1;
+ NRF_TIMER0->TASKS_SHUTDOWN = 1;
+ NRF_RTC0->EVTENCLR = RTC_EVTENSET_COMPARE0_Msk;
+}
+#endif
+/**
+ * ble phy disable irq and ppi
+ *
+ * This routine is to be called when reception was stopped due to either a
+ * wait for response timeout or a packet being received and the phy is to be
+ * restarted in receive mode. Generally, the disable routine is called to stop
+ * the phy.
+ */
+void
+ble_phy_disable_irq_and_ppi(void)
+{
NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
NRF_RADIO->SHORTS = 0;
NRF_RADIO->TASKS_DISABLE = 1;
- NRF_PPI->CHENCLR = PPI_CHEN_CH23_Msk | PPI_CHEN_CH21_Msk | PPI_CHEN_CH20_Msk;
+ NRF_PPI->CHENCLR = PPI_CHEN_CH4_Msk | PPI_CHEN_CH5_Msk | PPI_CHEN_CH20_Msk |
+ PPI_CHEN_CH21_Msk | PPI_CHEN_CH23_Msk | PPI_CHEN_CH24_Msk |
+ PPI_CHEN_CH25_Msk | PPI_CHEN_CH31_Msk;
NVIC_ClearPendingIRQ(RADIO_IRQn);
g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
}
+void
+ble_phy_restart_rx(void)
+{
+ ble_phy_disable_irq_and_ppi();
+ ble_phy_rx();
+}
+
+/**
+ * ble phy disable
+ *
+ * Disables the PHY. This should be called when an event is over. It stops
+ * the usec timer (if used), disables interrupts, disables the RADIO, disables
+ * PPI and sets state to idle.
+ */
+void
+ble_phy_disable(void)
+{
+ ble_ll_log(BLE_LL_LOG_ID_PHY_DISABLE, g_ble_phy_data.phy_state, 0, 0);
+ ble_phy_stop_usec_timer();
+ ble_phy_disable_irq_and_ppi();
+}
+
/* Gets the current access address */
uint32_t ble_phy_access_addr_get(void)
{
@@ -1168,3 +1514,17 @@ ble_phy_resolv_list_disable(void)
g_ble_phy_data.phy_privacy = 0;
}
#endif
+
+#ifdef BLE_XCVR_RFCLK
+void
+ble_phy_rfclk_enable(void)
+{
+ NRF_CLOCK->TASKS_HFCLKSTART = 1;
+}
+
+void
+ble_phy_rfclk_disable(void)
+{
+ NRF_CLOCK->TASKS_HFCLKSTOP = 1;
+}
+#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/kernel/os/include/os/os_cputime.h
----------------------------------------------------------------------
diff --git a/kernel/os/include/os/os_cputime.h b/kernel/os/include/os/os_cputime.h
index f44c941..022efdc 100644
--- a/kernel/os/include/os/os_cputime.h
+++ b/kernel/os/include/os/os_cputime.h
@@ -45,6 +45,10 @@ extern "C" {
#define OS_CPUTIME_FREQ_1MHZ
#endif
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
+#define OS_CPUTIME_FREQ_32768
+#endif
+
/* CPUTIME data. */
struct os_cputime_data
{
@@ -80,6 +84,7 @@ int os_cputime_init(uint32_t clock_freq);
*/
uint32_t os_cputime_get32(void);
+#if !defined(OS_CPUTIME_FREQ_32768)
/**
* os cputime nsecs to ticks
*
@@ -101,6 +106,7 @@ uint32_t os_cputime_nsecs_to_ticks(uint32_t nsecs);
* @return uint32_t The number of nanoseconds corresponding to 'ticks'
*/
uint32_t os_cputime_ticks_to_nsecs(uint32_t ticks);
+#endif
#if defined(OS_CPUTIME_FREQ_1MHZ)
#define os_cputime_usecs_to_ticks(x) (x)
@@ -138,6 +144,7 @@ uint32_t os_cputime_ticks_to_usecs(uint32_t ticks);
*/
void os_cputime_delay_ticks(uint32_t ticks);
+#if !defined(OS_CPUTIME_FREQ_32768)
/**
* os cputime delay nsecs
*
@@ -146,6 +153,7 @@ void os_cputime_delay_ticks(uint32_t ticks);
* @param nsecs The number of nanoseconds to wait.
*/
void os_cputime_delay_nsecs(uint32_t nsecs);
+#endif
/**
* os cputime delay usecs
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/kernel/os/src/os_cputime.c
----------------------------------------------------------------------
diff --git a/kernel/os/src/os_cputime.c b/kernel/os/src/os_cputime.c
index 067f1a1..01b15fe 100644
--- a/kernel/os/src/os_cputime.c
+++ b/kernel/os/src/os_cputime.c
@@ -30,7 +30,9 @@
* @{
*/
+#if !defined(OS_CPUTIME_FREQ_32768) && !defined(OS_CPUTIME_FREQ_1MHZ)
struct os_cputime_data g_os_cputime;
+#endif
/**
* os cputime init
@@ -49,11 +51,14 @@ os_cputime_init(uint32_t clock_freq)
int rc;
/* Set the ticks per microsecond. */
+#if !defined(OS_CPUTIME_FREQ_32768) && !defined(OS_CPUTIME_FREQ_1MHZ)
g_os_cputime.ticks_per_usec = clock_freq / 1000000U;
+#endif
rc = hal_timer_config(MYNEWT_VAL(OS_CPUTIME_TIMER_NUM), clock_freq);
return rc;
}
+#if !defined(OS_CPUTIME_FREQ_32768)
/**
* os cputime nsecs to ticks
*
@@ -99,8 +104,50 @@ os_cputime_ticks_to_nsecs(uint32_t ticks)
return nsecs;
}
+#endif
#if !defined(OS_CPUTIME_FREQ_1MHZ)
+#if defined(OS_CPUTIME_FREQ_32768)
+/**
+ * os cputime usecs to ticks
+ *
+ * Converts the given number of microseconds into cputime ticks.
+ *
+ * @param usecs The number of microseconds to convert to ticks
+ *
+ * @return uint32_t The number of ticks corresponding to 'usecs'
+ */
+uint32_t
+os_cputime_usecs_to_ticks(uint32_t usecs)
+{
+ uint64_t ticks;
+
+ ticks = ((uint64_t)usecs << 9) / 15625;
+ return (uint32_t)ticks;
+}
+
+/**
+ * cputime ticks to usecs
+ *
+ * Convert the given number of ticks into microseconds.
+ *
+ * @param ticks The number of ticks to convert to microseconds.
+ *
+ * @return uint32_t The number of microseconds corresponding to 'ticks'
+ *
+ * NOTE: This calculation will overflow if the value for ticks is greater
+ * than 140737488. I am not going to check that here because that many ticks
+ * is about 4222 seconds, way more than what this routine should be used for.
+ */
+uint32_t
+os_cputime_ticks_to_usecs(uint32_t ticks)
+{
+ uint32_t usecs;
+
+ usecs = ((ticks >> 9) * 15625) + (((ticks & 0x1ff) * 15625) >> 9);
+ return usecs;
+}
+#else
/**
* os cputime usecs to ticks
*
@@ -138,6 +185,7 @@ os_cputime_ticks_to_usecs(uint32_t ticks)
return us;
}
#endif
+#endif
/**
* os cputime delay ticks
@@ -157,6 +205,7 @@ os_cputime_delay_ticks(uint32_t ticks)
}
}
+#if !defined(OS_CPUTIME_FREQ_32768)
/**
* os cputime delay nsecs
*
@@ -172,6 +221,7 @@ os_cputime_delay_nsecs(uint32_t nsecs)
ticks = os_cputime_nsecs_to_ticks(nsecs);
os_cputime_delay_ticks(ticks);
}
+#endif
/**
* os cputime delay usecs
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/net/nimble/controller/include/controller/ble_ll.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll.h b/net/nimble/controller/include/controller/ble_ll.h
index e349d71..acc201d 100644
--- a/net/nimble/controller/include/controller/ble_ll.h
+++ b/net/nimble/controller/include/controller/ble_ll.h
@@ -22,13 +22,41 @@
#include "stats/stats.h"
#include "os/os_eventq.h"
+#include "os/os_callout.h"
#include "os/os_cputime.h"
#include "nimble/nimble_opt.h"
+#include "controller/ble_phy.h"
#ifdef __cplusplus
extern "C" {
#endif
+/*
+ * XXX:
+ * I guess this should not depend on the 32768 crystal to be honest. This
+ * should be done for TIMER0 as well since the rf clock chews up more current.
+ * Deal with this later.
+ *
+ * Another note: BLE_XTAL_SETTLE_TIME should be bsp related (I guess). There
+ * should be a note in there that the converted usecs to ticks value of this
+ * should not be 0. Thus: if you are using a 32.768 os cputime freq, the min
+ * value of settle time should be 31 usecs. I would suspect all settling times
+ * would exceed 31 usecs.
+ */
+
+/* Determines if we need to turn on/off rf clock */
+#undef BLE_XCVR_RFCLK
+
+/* Transceiver specific definitions */
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+
+/* We will turn on/off rf clock */
+#if MYNEWT_VAL(BLE_XTAL_SETTLE_TIME) != 0
+#define BLE_XCVR_RFCLK
+#endif
+
+#endif
+
/* Controller revision. */
#define BLE_LL_SUB_VERS_NR (0x0000)
@@ -61,11 +89,22 @@ struct ble_ll_obj
/* Number of ACL data packets supported */
uint8_t ll_num_acl_pkts;
+
+#ifdef BLE_XCVR_RFCLK
+ uint8_t ll_rfclk_state;
+ uint16_t ll_xtal_ticks;
+#else
uint8_t _pad;
+ uint16_t _pad16;
+#endif
/* ACL data packet size */
uint16_t ll_acl_pkt_size;
- uint16_t _pad16;
+
+#ifdef BLE_XCVR_RFCLK
+ uint32_t ll_rfclk_start_time;
+ struct hal_timer ll_rfclk_timer;
+#endif
/* Task event queue */
struct os_eventq ll_evq;
@@ -362,6 +401,9 @@ void ble_ll_wfr_enable(uint32_t cputime);
/* Disable wait for response timer */
void ble_ll_wfr_disable(void);
+/* Wait for response timer expiration callback */
+void ble_ll_wfr_timer_exp(void *arg);
+
/* Read set of features supported by the Link Layer */
uint8_t ble_ll_read_supp_features(void);
@@ -383,7 +425,7 @@ int ble_ll_rand_start(void);
* XXX: temporary LL debug log. Will get removed once we transition to real
* log
*/
-#undef BLE_LL_LOG
+#define BLE_LL_LOG
#include "console/console.h"
#define BLE_LL_LOG_ID_PHY_SETCHAN (1)
@@ -405,6 +447,11 @@ int ble_ll_rand_start(void);
#define BLE_LL_LOG_ID_ADV_TXBEG (50)
#define BLE_LL_LOG_ID_ADV_TXDONE (60)
#define BLE_LL_LOG_ID_SCHED (80)
+#define BLE_LL_LOG_ID_RFCLK_START (90)
+#define BLE_LL_LOG_ID_RFCLK_ENABLE (91)
+#define BLE_LL_LOG_ID_RFCLK_STOP (95)
+#define BLE_LL_LOG_ID_RFCLK_SCHED_DIS (96)
+#define BLE_LL_LOG_ID_RFCLK_SCAN_DIS (97)
#ifdef BLE_LL_LOG
void ble_ll_log(uint8_t id, uint8_t arg8, uint16_t arg16, uint32_t arg32);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/net/nimble/controller/include/controller/ble_ll_conn.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_conn.h b/net/nimble/controller/include/controller/ble_ll_conn.h
index b2e6410..041504d 100644
--- a/net/nimble/controller/include/controller/ble_ll_conn.h
+++ b/net/nimble/controller/include/controller/ble_ll_conn.h
@@ -202,6 +202,11 @@ struct ble_ll_conn_sm
uint16_t max_ce_len;
uint16_t tx_win_off;
uint32_t anchor_point;
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ uint8_t anchor_point_usecs; /* XXX: can this be uint8_t ?*/
+ uint8_t conn_itvl_usecs;
+ uint32_t conn_itvl_ticks;
+#endif
uint32_t last_anchor_point; /* Slave only */
uint32_t slave_cur_tx_win_usecs;
uint32_t slave_cur_window_widening;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/net/nimble/controller/include/controller/ble_ll_sched.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_sched.h b/net/nimble/controller/include/controller/ble_ll_sched.h
index 3a05cfe..d2321b7 100644
--- a/net/nimble/controller/include/controller/ble_ll_sched.h
+++ b/net/nimble/controller/include/controller/ble_ll_sched.h
@@ -25,7 +25,8 @@ extern "C" {
#endif
/* Time per BLE scheduler slot */
-#define BLE_LL_SCHED_USECS_PER_SLOT (1250)
+#define BLE_LL_SCHED_USECS_PER_SLOT (1250)
+#define BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT (41) /* 1 tick = 30.517 usecs */
/*
* Worst case time needed for scheduled advertising item. This is the longest
@@ -46,6 +47,17 @@ extern "C" {
#define BLE_LL_SCHED_DIRECT_ADV_MAX_USECS (502)
#define BLE_LL_SCHED_MAX_ADV_PDU_USECS (376)
+/* BLE Jitter (+/- 16 useecs) */
+#define BLE_LL_JITTER_USECS (16)
+
+/*
+ * This is the offset from the start of the scheduled item until the actual
+ * tx/rx should occur, in ticks.
+ */
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+extern uint8_t g_ble_ll_sched_offset_ticks;
+#endif
+
/*
* This is the number of slots needed to transmit and receive a maximum
* size PDU, including an IFS time before each. The actual time is
@@ -69,10 +81,19 @@ extern "C" {
struct ble_ll_sched_item;
typedef int (*sched_cb_func)(struct ble_ll_sched_item *sch);
+/*
+ * Schedule item
+ * sched_type: This is the type of the schedule item.
+ * enqueued: Flag denoting if item is on the scheduler list. 0: no, 1:yes
+ * remainder: # of usecs from offset till tx/rx should occur
+ * txrx_offset: Number of ticks from start time until tx/rx should occur.
+ *
+ */
struct ble_ll_sched_item
{
uint8_t sched_type;
uint8_t enqueued;
+ uint8_t remainder;
uint32_t start_time;
uint32_t end_time;
void *cb_arg;
@@ -94,8 +115,8 @@ void ble_ll_sched_free_item(struct ble_ll_sched_item *sch);
/* Schedule a new master connection */
struct ble_ll_conn_sm;
-int ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, uint32_t adv_rxend,
- uint8_t req_slots);
+int ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
+ struct ble_mbuf_hdr *ble_hdr, uint8_t pyld_len);
/* Schedule a new slave connection */
int ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm);
@@ -128,6 +149,11 @@ int ble_ll_sched_next_time(uint32_t *next_event_time);
/* Stop the scheduler */
void ble_ll_sched_stop(void);
+#ifdef BLE_XCVR_RFCLK
+/* Check if RF clock needs to be restarted */
+void ble_ll_sched_rfclk_chk_restart(void);
+#endif
+
#ifdef __cplusplus
}
#endif
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/net/nimble/controller/include/controller/ble_ll_xcvr.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_xcvr.h b/net/nimble/controller/include/controller/ble_ll_xcvr.h
new file mode 100644
index 0000000..c59b009
--- /dev/null
+++ b/net/nimble/controller/include/controller/ble_ll_xcvr.h
@@ -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_LL_XCVR_
+#define H_BLE_LL_XCVR_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef BLE_XCVR_RFCLK
+
+/* RF clock states */
+#define BLE_RFCLK_STATE_OFF (0)
+#define BLE_RFCLK_STATE_ON (1)
+#define BLE_RFCLK_STATE_SETTLED (2)
+
+int ble_ll_xcvr_rfclk_state(void);
+void ble_ll_xcvr_rfclk_start_now(uint32_t now);
+void ble_ll_xcvr_rfclk_stop(void);
+void ble_ll_xcvr_rfclk_enable(void);
+void ble_ll_xcvr_rfclk_disable(void);
+uint32_t ble_ll_xcvr_rfclk_time_till_settled(void);
+void ble_ll_xcvr_rfclk_timer_exp(void *arg);
+void ble_ll_xcvr_rfclk_timer_start(uint32_t cputime);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_LL_ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/net/nimble/controller/include/controller/ble_phy.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_phy.h b/net/nimble/controller/include/controller/ble_phy.h
index 674cbc5..e62b216 100644
--- a/net/nimble/controller/include/controller/ble_phy.h
+++ b/net/nimble/controller/include/controller/ble_phy.h
@@ -70,6 +70,7 @@ struct os_mbuf;
#define BLE_PHY_ERR_INV_PARAM (3)
#define BLE_PHY_ERR_NO_BUFS (4)
#define BLE_PHY_ERR_TX_LATE (5)
+#define BLE_PHY_ERR_RX_LATE (6)
/* Maximun PDU length. Includes LL header of 2 bytes and 255 bytes payload. */
#define BLE_PHY_MAX_PDU_LEN (257)
@@ -86,11 +87,16 @@ int ble_phy_reset(void);
/* Set the PHY channel */
int ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit);
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
/* Set transmit start time */
-int ble_phy_tx_set_start_time(uint32_t cputime);
+int ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs);
/* Set receive start time */
-int ble_phy_rx_set_start_time(uint32_t cputime);
+int ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs);
+#else
+/* Set transmit start time */
+int ble_phy_tx_set_start_time(uint32_t cputime);
+#endif
/* Set the transmit end callback and argument */
void ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg);
@@ -116,6 +122,27 @@ int ble_phy_txpwr_get(void);
/* Disable the PHY */
void ble_phy_disable(void);
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768)
+void ble_phy_stop_usec_timer(void);
+void ble_phy_wfr_enable(int txrx, uint32_t wfr_usecs);
+#define BLE_PHY_WFR_ENABLE_RX (0)
+#define BLE_PHY_WFR_ENABLE_TXRX (1)
+#else
+#define ble_phy_stop_usec_timer()
+#endif
+
+/* Starts rf clock */
+void ble_phy_rfclk_enable(void);
+
+/* Stops rf clock */
+void ble_phy_rfclk_disable(void);
+
+/*
+ * Used to restart reception on same channel after wfr timer expiration or
+ * frame received.
+ */
+void ble_phy_restart_rx(void);
+
/* Gets the current state of the PHY */
int ble_phy_state_get(void);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/net/nimble/controller/src/ble_ll.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll.c b/net/nimble/controller/src/ble_ll.c
index 6071d3c..3204ff2 100644
--- a/net/nimble/controller/src/ble_ll.c
+++ b/net/nimble/controller/src/ble_ll.c
@@ -39,6 +39,7 @@
#include "controller/ble_ll_hci.h"
#include "controller/ble_ll_whitelist.h"
#include "controller/ble_ll_resolv.h"
+#include "controller/ble_ll_xcvr.h"
#include "ble_ll_conn_priv.h"
/* XXX:
@@ -51,6 +52,11 @@
* 4) Should look into always disabled the wfr interrupt if we receive the
* start of a frame. Need to look at the various states to see if this is the
* right thing to do.
+ * 5) I am not sure that if we are passed the output compare that we actually
+ * get the interrupt. Test this.
+ * 6) I am not sure that if we receive a packet while scanning that we actually
+ * go back to scanning. I need to make sure we re-enable the receive.
+ * Put an event in the log!
*/
/* Supported states */
@@ -536,7 +542,9 @@ ble_ll_wfr_timer_exp(void *arg)
void
ble_ll_wfr_enable(uint32_t cputime)
{
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) != 32768
os_cputime_timer_start(&g_ble_ll_data.ll_wfr_timer, cputime);
+#endif
}
/**
@@ -545,7 +553,9 @@ ble_ll_wfr_enable(uint32_t cputime)
void
ble_ll_wfr_disable(void)
{
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) != 32768
os_cputime_timer_stop(&g_ble_ll_data.ll_wfr_timer);
+#endif
}
/**
@@ -786,7 +796,12 @@ ble_ll_rx_start(uint8_t *rxbuf, uint8_t chan, struct ble_mbuf_hdr *rxhdr)
int rc;
uint8_t pdu_type;
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ ble_ll_log(BLE_LL_LOG_ID_RX_START, chan, rxhdr->rem_usecs,
+ rxhdr->beg_cputime);
+#else
ble_ll_log(BLE_LL_LOG_ID_RX_START, chan, 0, rxhdr->beg_cputime);
+#endif
/* Check channel type */
if (chan < BLE_PHY_NUM_DATA_CHANS) {
@@ -1167,6 +1182,11 @@ ble_ll_reset(void)
/* Set state to standby */
ble_ll_state_set(BLE_LL_STATE_STANDBY);
+#ifdef BLE_XCVR_RFCLK
+ /* Stops rf clock and rfclock timer */
+ ble_ll_xcvr_rfclk_stop();
+#endif
+
/* Reset our random address */
memset(g_random_addr, 0, BLE_DEV_ADDR_LEN);
@@ -1211,11 +1231,26 @@ ble_ll_init(void)
{
int rc;
uint8_t features;
+#ifdef BLE_XCVR_RFCLK
+ uint32_t xtal_ticks;
+#endif
struct ble_ll_obj *lldata;
/* Ensure this function only gets called by sysinit. */
SYSINIT_ASSERT_ACTIVE();
+#ifdef BLE_XCVR_RFCLK
+ /* Settling time of crystal, in ticks */
+ xtal_ticks = MYNEWT_VAL(BLE_XTAL_SETTLE_TIME);
+ assert(xtal_ticks != 0);
+ g_ble_ll_data.ll_xtal_ticks = os_cputime_usecs_to_ticks(xtal_ticks);
+
+ /* Initialize rf clock timer */
+ os_cputime_timer_init(&g_ble_ll_data.ll_rfclk_timer,
+ ble_ll_xcvr_rfclk_timer_exp, NULL);
+
+#endif
+
/* Get pointer to global data object */
lldata = &g_ble_ll_data;
@@ -1241,9 +1276,11 @@ ble_ll_init(void)
ble_ll_hw_err_timer_cb,
NULL);
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) != 32768
/* Initialize wait for response timer */
os_cputime_timer_init(&g_ble_ll_data.ll_wfr_timer, ble_ll_wfr_timer_exp,
NULL);
+#endif
/* Initialize LL HCI */
ble_ll_hci_init();
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/net/nimble/controller/src/ble_ll_adv.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_adv.c b/net/nimble/controller/src/ble_ll_adv.c
index 203f13a..8240d7a 100644
--- a/net/nimble/controller/src/ble_ll_adv.c
+++ b/net/nimble/controller/src/ble_ll_adv.c
@@ -430,8 +430,14 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch)
assert(rc == 0);
/* Set transmit start time. */
- txstart = sch->start_time + os_cputime_usecs_to_ticks(XCVR_PROC_DELAY_USECS);
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ txstart = sch->start_time + g_ble_ll_sched_offset_ticks;
+ rc = ble_phy_tx_set_start_time(txstart, sch->remainder);
+#else
+ txstart = sch->start_time +
+ os_cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS);
rc = ble_phy_tx_set_start_time(txstart);
+#endif
if (rc) {
STATS_INC(ble_ll_stats, adv_late_starts);
goto adv_tx_done;
@@ -498,7 +504,7 @@ adv_tx_done:
}
static void
-ble_ll_adv_set_sched(struct ble_ll_adv_sm *advsm, int sched_new)
+ble_ll_adv_set_sched(struct ble_ll_adv_sm *advsm)
{
uint32_t max_usecs;
struct ble_ll_sched_item *sch;
@@ -529,20 +535,15 @@ ble_ll_adv_set_sched(struct ble_ll_adv_sm *advsm, int sched_new)
*/
max_usecs += XCVR_PROC_DELAY_USECS;
- if (sched_new) {
- /*
- * We have to add the scheduling delay and tx start delay to the max
- * time of the event since the pdu does not start at the scheduled start.
- */
- max_usecs += XCVR_TX_SCHED_DELAY_USECS;
- sch->start_time = os_cputime_get32();
- sch->end_time = sch->start_time + os_cputime_usecs_to_ticks(max_usecs);
- } else {
- sch->start_time = advsm->adv_pdu_start_time -
- os_cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS);
- sch->end_time = advsm->adv_pdu_start_time +
- os_cputime_usecs_to_ticks(max_usecs);
- }
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ sch->start_time = advsm->adv_pdu_start_time - g_ble_ll_sched_offset_ticks;
+ sch->remainder = 0;
+#else
+ sch->start_time = advsm->adv_pdu_start_time -
+ os_cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS);
+#endif
+ sch->end_time = advsm->adv_pdu_start_time +
+ os_cputime_usecs_to_ticks(max_usecs);
}
/**
@@ -745,6 +746,10 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm)
ble_ll_wfr_disable();
ble_ll_state_set(BLE_LL_STATE_STANDBY);
g_ble_ll_cur_adv_sm = NULL;
+ ble_ll_scan_chk_resume();
+#ifdef BLE_XCVR_RFCLK
+ ble_ll_sched_rfclk_chk_restart();
+#endif
}
#else
if (ble_ll_state_get() == BLE_LL_STATE_ADV) {
@@ -752,6 +757,10 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm)
ble_ll_wfr_disable();
ble_ll_state_set(BLE_LL_STATE_STANDBY);
g_ble_ll_cur_adv_sm = NULL;
+ ble_ll_scan_chk_resume();
+#ifdef BLE_XCVR_RFCLK
+ ble_ll_sched_rfclk_chk_restart();
+#endif
}
#endif
OS_EXIT_CRITICAL(sr);
@@ -872,10 +881,23 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
advsm->adv_chan = adv_chan;
/*
+ * XXX: while this may not be the most efficient, schedule the first
+ * advertising event some time in the future (5 msecs). This will give
+ * time to start up any clocks or anything and also avoid a bunch of code
+ * to check if we are currently doing anything. Just makes this simple.
+ *
+ * Might also want to align this on a slot in the future.
+ *
+ * NOTE: adv_event_start_time gets set by the sched_adv_new
+ */
+ advsm->adv_pdu_start_time = os_cputime_get32() +
+ os_cputime_usecs_to_ticks(BLE_LL_SCHED_MAX_TXRX_SLOT);
+
+ /*
* Schedule advertising. We set the initial schedule start and end
* times to the earliest possible start/end.
*/
- ble_ll_adv_set_sched(advsm, 1);
+ ble_ll_adv_set_sched(advsm);
ble_ll_sched_adv_new(&advsm->adv_sch);
return BLE_ERR_SUCCESS;
@@ -884,9 +906,14 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
void
ble_ll_adv_scheduled(struct ble_ll_adv_sm *advsm, uint32_t sch_start)
{
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ /* The event start time is when we start transmission of the adv PDU */
+ advsm->adv_event_start_time = sch_start + g_ble_ll_sched_offset_ticks;
+#else
/* The event start time is when we start transmission of the adv PDU */
advsm->adv_event_start_time = sch_start +
os_cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS);
+#endif
advsm->adv_pdu_start_time = advsm->adv_event_start_time;
@@ -1489,6 +1516,11 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm)
/* Check if we need to resume scanning */
ble_ll_scan_chk_resume();
+ /* Turn off the clock if not doing anything else */
+#ifdef BLE_XCVR_RFCLK
+ ble_ll_sched_rfclk_chk_restart();
+#endif
+
/* This event is over. Set adv channel to first one */
advsm->adv_chan = ble_ll_adv_first_chan(advsm);
@@ -1511,8 +1543,12 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm)
* The scheduled time better be in the future! If it is not, we will
* just keep advancing until we the time is in the future
*/
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ start_time = advsm->adv_pdu_start_time - g_ble_ll_sched_offset_ticks;
+#else
start_time = advsm->adv_pdu_start_time -
os_cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS);
+#endif
delta_t = (int32_t)(start_time - os_cputime_get32());
if (delta_t < 0) {
@@ -1543,9 +1579,13 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm)
* We will transmit right away. Set next pdu start time to now
* plus a xcvr start delay just so we dont count late adv starts
*/
- advsm->adv_pdu_start_time = os_cputime_get32() +
+ advsm->adv_pdu_start_time = os_cputime_get32();
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ advsm->adv_pdu_start_time += g_ble_ll_sched_offset_ticks;
+#else
+ advsm->adv_pdu_start_time +=
os_cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS);
-
+#endif
resched_pdu = 1;
}
@@ -1571,7 +1611,7 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm)
#endif
/* Schedule advertising transmit */
- ble_ll_adv_set_sched(advsm, 0);
+ ble_ll_adv_set_sched(advsm);
/*
* In the unlikely event we cant reschedule this, just post a done
@@ -1580,9 +1620,15 @@ ble_ll_adv_done(struct ble_ll_adv_sm *advsm)
if (resched_pdu) {
rc = ble_ll_sched_adv_resched_pdu(&advsm->adv_sch);
} else {
+ /* Reschedule advertising event */
rc = ble_ll_sched_adv_reschedule(&advsm->adv_sch, &start_time,
max_delay_ticks);
if (!rc) {
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ start_time += g_ble_ll_sched_offset_ticks;
+#else
+ start_time += os_cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS);
+#endif
advsm->adv_event_start_time = start_time;
advsm->adv_pdu_start_time = start_time;
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/net/nimble/controller/src/ble_ll_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn.c b/net/nimble/controller/src/ble_ll_conn.c
index 1d2714a..d7f926e 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -95,15 +95,26 @@ extern void bletest_completed_pkt(uint16_t handle);
* response. Well, it should. If this packet will overrun the next scheduled
* event, what should we do? Transmit anyway? Not transmit? For now, we just
* transmit.
+ *
+ * 32kHz crystal
+ * 1) When scheduling, I need to make sure I have time between
+ * this one and the next. Should I deal with this in the sched. Or
+ * is this basically accounted for given a slot? I really just need to
+ * make sure everything is over N ticks before the next sched start!
+ * Just add to end time?
+ *
+ * 2) I think one way to handle the problem of losing up to a microsecond
+ * every time we call ble_ll_conn_next_event in a loop is to do everything by
+ * keeping track of last anchor point. Would need last anchor usecs too. I guess
+ * we could also keep last anchor usecs as a uint32 or something and when we
+ * do the next event keep track of the residual using a different ticks to
+ * usecs calculation. Not sure.
*/
/*
* XXX: How should we deal with a late connection event? We need to determine
* what we want to do under the following cases:
* 1) The current connection event has not ended but a schedule item starts
- * 2) The connection event start cb is called but we are later than we
- * expected. What to do? If we cant transmit at correct point in slot we
- * are hosed. Well, anchor point can get really messed up!
*/
/*
@@ -218,6 +229,25 @@ STATS_NAME_END(ble_ll_conn_stats)
static void ble_ll_conn_event_end(struct os_event *ev);
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+static void
+ble_ll_conn_calc_itvl_ticks(struct ble_ll_conn_sm *connsm)
+{
+ uint32_t ticks;
+ uint32_t usecs;
+
+ /*
+ * Precalculate the number of ticks and remaining microseconds for
+ * the connection interval
+ */
+ usecs = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS;
+ ticks = os_cputime_usecs_to_ticks(usecs);
+ connsm->conn_itvl_ticks = ticks;
+ connsm->conn_itvl_usecs = (uint8_t)(usecs -
+ os_cputime_ticks_to_usecs(ticks));
+}
+#endif
+
/**
* Get the event buffer allocated to send the connection complete event
* when we are initiating.
@@ -402,7 +432,6 @@ ble_ll_conn_calc_window_widening(struct ble_ll_conn_sm *connsm)
window_widening = (total_sca_ppm * delta_msec) / 1000;
}
- /* XXX: spec gives 16 usecs error btw. Probably should add that in */
return window_widening;
}
@@ -689,7 +718,10 @@ ble_ll_conn_continue_rx_encrypt(void *arg)
* the current connection event. The current connection event must end before
* the next scheduled item. However, the current connection itself is not
* in the scheduler list! Thus, we need to calculate the time at which the
- * next connection will start and not overrun it.
+ * next connection will start (the schedule start time; not the anchor point)
+ * and not overrun it.
+ *
+ * Context: Interrupt
*
* @param connsm
*
@@ -698,13 +730,25 @@ ble_ll_conn_continue_rx_encrypt(void *arg)
static uint32_t
ble_ll_conn_get_next_sched_time(struct ble_ll_conn_sm *connsm)
{
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) != 32768
uint32_t itvl;
+#endif
uint32_t ce_end;
uint32_t next_sched_time;
/* Calculate time at which next connection event will start */
- itvl = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS;
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ /* NOTE: We dont care if this time is tick short. */
+ ce_end = connsm->anchor_point + connsm->conn_itvl_ticks -
+ g_ble_ll_sched_offset_ticks;
+ if ((connsm->anchor_point_usecs + connsm->conn_itvl_usecs) >= 31) {
+ ++ce_end;
+ }
+#else
+ itvl = (connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS) -
+ XCVR_TX_SCHED_DELAY_USECS;
ce_end = connsm->anchor_point + os_cputime_usecs_to_ticks(itvl);
+#endif
if (ble_ll_sched_next_time(&next_sched_time)) {
if (CPUTIME_LT(next_sched_time, ce_end)) {
@@ -1121,8 +1165,10 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch)
{
int rc;
uint32_t usecs;
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) != 32768
uint32_t wfr_time;
- uint32_t txstart;
+#endif
+ uint32_t start;
struct ble_ll_conn_sm *connsm;
/* XXX: note that we can extend end time here if we want. Look at this */
@@ -1151,9 +1197,15 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch)
#endif
if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ /* Set start time of transmission */
+ start = sch->start_time + g_ble_ll_sched_offset_ticks;
+ rc = ble_phy_tx_set_start_time(start, sch->remainder);
+#else
/* Set start time of transmission */
- txstart = sch->start_time + os_cputime_usecs_to_ticks(XCVR_PROC_DELAY_USECS);
- rc = ble_phy_tx_set_start_time(txstart);
+ start = sch->start_time + os_cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS);
+ rc = ble_phy_tx_set_start_time(start);
+#endif
if (!rc) {
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
if (CONN_F_ENCRYPTED(connsm)) {
@@ -1187,11 +1239,13 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch)
ble_phy_encrypt_disable();
}
#endif
- /*
- * XXX: make sure I dont care that I get here early to start receiving.
- * I could use events compare and all that shit to start rx.
- */
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ /* XXX: what is this really for the slave? */
+ start = sch->start_time + g_ble_ll_sched_offset_ticks;
+ rc = ble_phy_rx_set_start_time(start, sch->remainder);
+#else
rc = ble_phy_rx();
+#endif
if (rc) {
/* End the connection event as we have no more buffers */
STATS_INC(ble_ll_conn_stats, slave_ce_failures);
@@ -1207,15 +1261,35 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch)
* Set the wait for response time. The anchor point is when we
* expect the master to start transmitting. Worst-case, we expect
* to hear a reply within the anchor point plus:
- * -> the current tx window size
- * -> The current window widening amount
+ * -> current tx window size
+ * -> current window widening amount (includes +/- 16 usec jitter)
* -> Amount of time it takes to detect packet start.
+ * -> Some extra time (16 usec) to insure timing is OK
+ */
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ /*
+ * For the 32 kHz crystal, the amount of usecs we have to wait
+ * is not from the anchor point; we have to account for the time
+ * from when the receiver is enabled until the anchor point. The
+ * time we start before the anchor point is this:
+ * -> current window widening.
+ * -> up to one 32 kHz tick since we discard remainder.
+ * -> Up to one tick since the usecs to ticks calc can be off
+ * by up to one tick.
+ * NOTES:
+ * 1) the 61 we add is for the two ticks mentioned above.
+ * 2) The address rx time and jitter is accounted for in the
+ * phy function
*/
+ usecs = connsm->slave_cur_tx_win_usecs + 61 +
+ (2 * connsm->slave_cur_window_widening);
+ ble_phy_wfr_enable(BLE_PHY_WFR_ENABLE_RX, usecs);
+#else
usecs = connsm->slave_cur_tx_win_usecs + BLE_LL_WFR_USECS +
connsm->slave_cur_window_widening;
wfr_time = connsm->anchor_point + os_cputime_usecs_to_ticks(usecs);
ble_ll_wfr_enable(wfr_time);
-
+#endif
/* Set next wakeup time to connection event end time */
rc = BLE_LL_SCHED_STATE_RUNNING;
}
@@ -1246,15 +1320,20 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch)
* @return int 0: not allowed to send 1: allowed to send
*/
static int
-ble_ll_conn_can_send_next_pdu(struct ble_ll_conn_sm *connsm, uint32_t begtime)
+ble_ll_conn_can_send_next_pdu(struct ble_ll_conn_sm *connsm, uint32_t begtime,
+ uint32_t add_usecs)
{
int rc;
uint8_t rem_bytes;
uint32_t ticks;
+ uint32_t usecs;
uint32_t next_sched_time;
struct os_mbuf *txpdu;
struct os_mbuf_pkthdr *pkthdr;
struct ble_mbuf_hdr *txhdr;
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ uint32_t allowed_usecs;
+#endif
rc = 1;
if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
@@ -1277,16 +1356,25 @@ ble_ll_conn_can_send_next_pdu(struct ble_ll_conn_sm *connsm, uint32_t begtime)
if (rem_bytes > connsm->eff_max_tx_octets) {
rem_bytes = connsm->eff_max_tx_octets;
}
- ticks = BLE_TX_DUR_USECS_M(rem_bytes);
+ usecs = BLE_TX_DUR_USECS_M(rem_bytes);
} else {
/* We will send empty pdu (just a LL header) */
- ticks = BLE_TX_DUR_USECS_M(0);
+ usecs = BLE_TX_DUR_USECS_M(0);
}
- ticks += (BLE_LL_IFS * 2) + connsm->eff_max_rx_time;
- ticks = os_cputime_usecs_to_ticks(ticks);
+ usecs += (BLE_LL_IFS * 2) + connsm->eff_max_rx_time;
+
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ ticks = (uint32_t)(next_sched_time - begtime);
+ allowed_usecs = os_cputime_ticks_to_usecs(ticks);
+ if ((usecs + add_usecs) >= allowed_usecs) {
+ rc = 0;
+ }
+#else
+ ticks = os_cputime_usecs_to_ticks(usecs);
if ((begtime + ticks) >= next_sched_time) {
rc = 0;
}
+#endif
}
return rc;
@@ -1347,7 +1435,15 @@ ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm,
connsm->conn_role = BLE_LL_CONN_ROLE_MASTER;
/* Set default ce parameters */
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ /*
+ * XXX: for now, we need twice the transmit window as our calculations
+ * for the transmit window offset could be off.
+ */
+ connsm->tx_win_size = BLE_LL_CONN_TX_WIN_MIN + 1;
+#else
connsm->tx_win_size = BLE_LL_CONN_TX_WIN_MIN;
+#endif
connsm->tx_win_off = 0;
connsm->master_sca = MYNEWT_VAL(BLE_LL_MASTER_SCA);
@@ -1482,6 +1578,10 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
connsm);
#endif
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ ble_ll_conn_calc_itvl_ticks(connsm);
+#endif
+
/* Add to list of active connections */
SLIST_INSERT_HEAD(&g_ble_ll_conn_active_list, connsm, act_sle);
}
@@ -1629,6 +1729,11 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
uint32_t cur_ww;
uint32_t max_ww;
struct ble_ll_conn_upd_req *upd;
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ uint32_t ticks;
+ uint32_t usecs;
+#endif
+
/* XXX: deal with connection request procedure here as well */
ble_ll_conn_chk_csm_flags(connsm);
@@ -1647,7 +1752,24 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
connsm->event_cntr += latency;
/* Set next connection event start time */
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ /* We can use pre-calculated values for one interval if latency is 1. */
+ if (latency == 1) {
+ connsm->anchor_point += connsm->conn_itvl_ticks;
+ connsm->anchor_point_usecs += connsm->conn_itvl_usecs;
+ } else {
+ uint32_t ticks;
+ ticks = os_cputime_usecs_to_ticks(itvl);
+ connsm->anchor_point += ticks;
+ connsm->anchor_point_usecs += (itvl - os_cputime_ticks_to_usecs(ticks));
+ }
+ if (connsm->anchor_point_usecs >= 31) {
+ ++connsm->anchor_point;
+ connsm->anchor_point_usecs -= 31;
+ }
+#else
connsm->anchor_point += os_cputime_usecs_to_ticks(itvl);
+#endif
/*
* If a connection update has been scheduled and the event counter
@@ -1669,15 +1791,30 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
connsm->csmflags.cfbit.host_expects_upd_event = 1;
}
- connsm->conn_itvl = upd->interval;
connsm->supervision_tmo = upd->timeout;
connsm->slave_latency = upd->latency;
connsm->tx_win_size = upd->winsize;
connsm->slave_cur_tx_win_usecs =
connsm->tx_win_size * BLE_LL_CONN_TX_WIN_USECS;
connsm->tx_win_off = upd->winoffset;
+ connsm->conn_itvl = upd->interval;
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ ble_ll_conn_calc_itvl_ticks(connsm);
+ if (upd->winoffset != 0) {
+ usecs = upd->winoffset * BLE_LL_CONN_ITVL_USECS;
+ ticks = os_cputime_usecs_to_ticks(usecs);
+ connsm->anchor_point += ticks;
+ usecs = usecs - os_cputime_ticks_to_usecs(ticks);
+ connsm->anchor_point_usecs += usecs;
+ if (connsm->anchor_point_usecs >= 31) {
+ ++connsm->anchor_point;
+ connsm->anchor_point_usecs -= 31;
+ }
+ }
+#else
connsm->anchor_point +=
os_cputime_usecs_to_ticks(upd->winoffset * BLE_LL_CONN_ITVL_USECS);
+#endif
/* Reset the starting point of the connection supervision timeout */
connsm->last_rxd_pdu_cputime = connsm->anchor_point;
@@ -1736,20 +1873,35 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
* Calculate ce end time. For a slave, we need to add window widening and
* the transmit window if we still have one.
*/
- itvl = MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * BLE_LL_SCHED_USECS_PER_SLOT;
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ itvl = MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT;
if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
cur_ww = ble_ll_conn_calc_window_widening(connsm);
max_ww = (connsm->conn_itvl * (BLE_LL_CONN_ITVL_USECS/2)) - BLE_LL_IFS;
if (cur_ww >= max_ww) {
return -1;
}
+ cur_ww += BLE_LL_JITTER_USECS;
connsm->slave_cur_window_widening = cur_ww;
+ itvl += os_cputime_usecs_to_ticks(cur_ww + connsm->slave_cur_tx_win_usecs);
+ }
+ itvl -= g_ble_ll_sched_offset_ticks;
+ connsm->ce_end_time = connsm->anchor_point + itvl;
+#else
+ itvl = MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * BLE_LL_SCHED_USECS_PER_SLOT;
+ if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
+ cur_ww = ble_ll_conn_calc_window_widening(connsm);
+ max_ww = (connsm->conn_itvl * (BLE_LL_CONN_ITVL_USECS/2)) - BLE_LL_IFS;
+ if (cur_ww >= max_ww) {
+ return -1;
+ }
+ connsm->slave_cur_window_widening = cur_ww + BLE_LL_JITTER_USECS;
itvl += cur_ww + connsm->slave_cur_tx_win_usecs;
} else {
- /* We adjust end time for connection to end of time slot */
itvl -= XCVR_TX_SCHED_DELAY_USECS;
}
connsm->ce_end_time = connsm->anchor_point + os_cputime_usecs_to_ticks(itvl);
+#endif
return 0;
}
@@ -1799,9 +1951,38 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr)
*/
rc = 1;
if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ /*
+ * With a 32.768 kHz crystal we dont care about the remaining usecs
+ * when setting last anchor point. The only thing last anchor is used
+ * for is to calculate window widening. The effect of this is
+ * negligible.
+ */
+ connsm->last_anchor_point = rxhdr->beg_cputime;
+
+ usecs = rxhdr->rem_usecs + 1250 +
+ (connsm->tx_win_off * BLE_LL_CONN_TX_WIN_USECS) +
+ BLE_TX_DUR_USECS_M(BLE_CONNECT_REQ_LEN);
+
+ /* Anchor point is cputime. */
+ endtime = os_cputime_usecs_to_ticks(usecs);
+ connsm->anchor_point = rxhdr->beg_cputime + endtime;
+ connsm->anchor_point_usecs = usecs - os_cputime_ticks_to_usecs(endtime);
+ if (connsm->anchor_point_usecs == 31) {
+ ++connsm->anchor_point;
+ connsm->anchor_point_usecs = 0;
+ }
+
+ connsm->slave_cur_tx_win_usecs =
+ connsm->tx_win_size * BLE_LL_CONN_TX_WIN_USECS;
+
+ connsm->ce_end_time = connsm->anchor_point +
+ (MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT)
+ + os_cputime_usecs_to_ticks(connsm->slave_cur_tx_win_usecs) + 1;
+#else
+ connsm->last_anchor_point = rxhdr->beg_cputime;
endtime = rxhdr->beg_cputime +
os_cputime_usecs_to_ticks(BLE_TX_DUR_USECS_M(BLE_CONNECT_REQ_LEN));
- connsm->last_anchor_point = endtime;
connsm->slave_cur_tx_win_usecs =
connsm->tx_win_size * BLE_LL_CONN_TX_WIN_USECS;
usecs = 1250 + (connsm->tx_win_off * BLE_LL_CONN_TX_WIN_USECS);
@@ -1810,7 +1991,8 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, struct ble_mbuf_hdr *rxhdr)
(MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS) * BLE_LL_SCHED_USECS_PER_SLOT);
connsm->ce_end_time = connsm->anchor_point +
os_cputime_usecs_to_ticks(usecs);
- connsm->slave_cur_window_widening = 0;
+#endif
+ connsm->slave_cur_window_widening = BLE_LL_JITTER_USECS;
/* Start the scheduler for the first connection event */
while (ble_ll_sched_slave_new(connsm)) {
@@ -1870,6 +2052,10 @@ ble_ll_conn_event_end(struct os_event *ev)
/* Check if we need to resume scanning */
ble_ll_scan_chk_resume();
+#ifdef BLE_XCVR_RFCLK
+ ble_ll_sched_rfclk_chk_restart();
+#endif
+
/* If we have transmitted the terminate IND successfully, we are done */
if ((connsm->csmflags.cfbit.terminate_ind_txd) ||
(connsm->csmflags.cfbit.terminate_ind_rxd)) {
@@ -1958,6 +2144,7 @@ ble_ll_conn_event_end(struct os_event *ev)
} else {
tmo = connsm->supervision_tmo * BLE_HCI_CONN_SPVN_TMO_UNITS * 1000UL;
}
+ /* XXX: Convert to ticks to usecs calculation instead??? */
tmo = os_cputime_usecs_to_ticks(tmo);
if ((int32_t)(connsm->anchor_point - connsm->last_rxd_pdu_cputime) >= tmo) {
ble_ll_conn_end(connsm, BLE_ERR_CONN_SPVN_TMO);
@@ -2251,7 +2438,6 @@ ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok,
uint8_t *init_addr = NULL;
uint8_t pyld_len;
uint8_t inita_is_rpa;
- uint32_t endtime;
struct os_mbuf *rxpdu;
struct ble_ll_conn_sm *connsm;
@@ -2366,10 +2552,7 @@ ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok,
}
/* Attempt to schedule new connection. Possible that this might fail */
- endtime = ble_hdr->beg_cputime +
- os_cputime_usecs_to_ticks(BLE_TX_DUR_USECS_M(pyld_len));
- if (!ble_ll_sched_master_new(connsm, endtime,
- MYNEWT_VAL(BLE_LL_CONN_INIT_SLOTS))) {
+ if (!ble_ll_sched_master_new(connsm, ble_hdr, pyld_len)) {
/* Setup to transmit the connect request */
rc = ble_ll_conn_request_send(addr_type, adv_addr,
connsm->tx_win_off, index);
@@ -2392,8 +2575,6 @@ init_rx_isr_exit:
*/
rxpdu = ble_ll_rxpdu_alloc(pyld_len + BLE_LL_PDU_HDR_LEN);
if (rxpdu == NULL) {
- ble_phy_disable();
-
/*
* XXX: possible allocate the PDU when we start initiating?
* I cannot say I like this solution, but if we cannot allocate a PDU
@@ -2405,8 +2586,7 @@ init_rx_isr_exit:
CONN_F_CONN_REQ_TXD(connsm) = 0;
ble_ll_sched_rmv_elem(&connsm->conn_sch);
}
-
- ble_phy_rx();
+ ble_phy_restart_rx();
rc = 0;
} else {
ble_phy_rxpdu_copy(rxbuf, rxpdu);
@@ -2498,6 +2678,9 @@ ble_ll_conn_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa)
connsm->csmflags.cfbit.slave_set_last_anchor = 0;
connsm->last_anchor_point = rxhdr->beg_cputime;
connsm->anchor_point = connsm->last_anchor_point;
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ connsm->anchor_point_usecs = rxhdr->rem_usecs;
+#endif
}
}
return 1;
@@ -2659,6 +2842,7 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
uint8_t opcode = 0;
uint8_t rx_pyld_len;
uint32_t endtime;
+ uint32_t add_usecs;
struct os_mbuf *txpdu;
struct ble_ll_conn_sm *connsm;
struct os_mbuf *rxpdu;
@@ -2689,8 +2873,14 @@ ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
}
/* Calculate the end time of the received PDU */
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ endtime = rxhdr->beg_cputime;
+ add_usecs = rxhdr->rem_usecs + BLE_TX_DUR_USECS_M(rx_pyld_len);
+#else
endtime = rxhdr->beg_cputime +
os_cputime_usecs_to_ticks(BLE_TX_DUR_USECS_M(rx_pyld_len));
+ add_usecs = 0;
+#endif
/*
* Check the packet CRC. A connection event can continue even if the
@@ -2861,7 +3051,7 @@ chk_rx_terminate_ind:
if (rx_pyld_len && CONN_F_ENCRYPTED(connsm)) {
rx_pyld_len += BLE_LL_DATA_MIC_LEN;
}
- if (reply && ble_ll_conn_can_send_next_pdu(connsm, endtime)) {
+ if (reply && ble_ll_conn_can_send_next_pdu(connsm, endtime, add_usecs)) {
rc = ble_ll_conn_tx_data_pdu(connsm);
}
@@ -3045,7 +3235,6 @@ ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, uint8_t *chanmap)
* Context: Link Layer
*
* @param rxbuf Pointer to received Connect Request PDU
- * @param conn_req_end receive end time of connect request
*
* @return 0: connection not started; 1 connecton started
*/
@@ -3269,3 +3458,5 @@ ble_ll_conn_module_init(void)
/* Call reset to finish reset of initialization */
ble_ll_conn_module_reset();
}
+
+
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/net/nimble/controller/src/ble_ll_conn_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn_priv.h b/net/nimble/controller/src/ble_ll_conn_priv.h
index 0913892..02cac60 100644
--- a/net/nimble/controller/src/ble_ll_conn_priv.h
+++ b/net/nimble/controller/src/ble_ll_conn_priv.h
@@ -42,12 +42,13 @@ extern "C" {
#define BLE_LL_CONN_INITIAL_OFFSET (1250)
#define BLE_LL_CONN_ITVL_USECS (1250)
#define BLE_LL_CONN_TX_WIN_USECS (1250)
+#define BLE_LL_CONN_TX_OFF_USECS (1250)
#define BLE_LL_CONN_CE_USECS (625)
#define BLE_LL_CONN_TX_WIN_MIN (1) /* in tx win units */
#define BLE_LL_CONN_SLAVE_LATENCY_MAX (499)
/* Connection request duration (in usecs) */
-#define BLE_LL_CONN_REQ_DURATION (352)
+#define BLE_LL_CONN_REQ_DURATION (352) /* 1 Mbps only */
/* Connection handle range */
#define BLE_LL_CONN_MAX_CONN_HANDLE (0x0EFF)
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/507f493a/net/nimble/controller/src/ble_ll_scan.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_scan.c b/net/nimble/controller/src/ble_ll_scan.c
index f732753..f5eca7f 100644
--- a/net/nimble/controller/src/ble_ll_scan.c
+++ b/net/nimble/controller/src/ble_ll_scan.c
@@ -37,6 +37,7 @@
#include "controller/ble_ll_hci.h"
#include "controller/ble_ll_whitelist.h"
#include "controller/ble_ll_resolv.h"
+#include "controller/ble_ll_xcvr.h"
#include "hal/hal_gpio.h"
/*
@@ -588,8 +589,14 @@ ble_ll_scan_start(struct ble_ll_scan_sm *scansm, uint8_t chan)
}
#endif
- /* Start receiving */
- rc = ble_phy_rx();
+#if MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768
+ /* XXX: probably need to make sure hfxo is running too */
+ /* XXX: can make this better; want to just start asap. */
+ rc = ble_phy_rx_set_start_time(os_cputime_get32() +
+ g_ble_ll_sched_offset_ticks, 0);
+#else
+ rc = ble_phy_rx();
+#endif
if (!rc) {
/* Enable/disable whitelisting */
if (scansm->scan_filt_policy & 1) {
@@ -612,6 +619,37 @@ ble_ll_scan_start(struct ble_ll_scan_sm *scansm, uint8_t chan)
}
}
+#ifdef BLE_XCVR_RFCLK
+static void
+ble_ll_scan_rfclk_chk_stop(void)
+{
+ int stop;
+ int32_t time_till_next;
+ os_sr_t sr;
+ uint32_t next_time;
+
+ stop = 0;
+ OS_ENTER_CRITICAL(sr);
+ if (ble_ll_sched_next_time(&next_time)) {
+ /*
+ * If the time until the next event is too close, dont bother to turn
+ * off the clock
+ */
+ time_till_next = (int32_t)(next_time - os_cputime_get32());
+ if (time_till_next > g_ble_ll_data.ll_xtal_ticks) {
+ stop = 1;
+ }
+ } else {
+ stop = 1;
+ }
+ if (stop) {
+ ble_ll_log(BLE_LL_LOG_ID_RFCLK_SCAN_DIS, g_ble_ll_data.ll_rfclk_state,0,0);
+ ble_ll_xcvr_rfclk_disable();
+ }
+ OS_EXIT_CRITICAL(sr);
+}
+#endif
+
/**
* Called to determine if we are inside or outside the scan window. If we
* are inside the scan window it means that the device should be receiving
@@ -629,6 +667,7 @@ ble_ll_scan_window_chk(struct ble_ll_scan_sm *scansm, uint32_t cputime)
int rc;
uint8_t chan;
uint32_t itvl;
+ uint32_t dt;
uint32_t win_start;
itvl = os_cputime_usecs_to_ticks(scansm->scan_itvl * BLE_HCI_SCAN_ITVL);
@@ -645,7 +684,13 @@ ble_ll_scan_window_chk(struct ble_ll_scan_sm *scansm, uint32_t cputime)
rc = 0;
if (scansm->scan_window != scansm->scan_itvl) {
itvl = os_cputime_usecs_to_ticks(scansm->scan_window * BLE_HCI_SCAN_ITVL);
- if ((cputime - win_start) >= itvl) {
+ dt = cputime - win_start;
+ if (dt >= itvl) {
+#ifdef BLE_XCVR_RFCLK
+ if (dt < (scansm->scan_itvl - g_ble_ll_data.ll_xtal_ticks)) {
+ ble_ll_scan_rfclk_chk_stop();
+ }
+#endif
rc = 1;
}
}
@@ -688,6 +733,11 @@ ble_ll_scan_sm_stop(int chk_disable)
/* Set LL state to standby */
ble_ll_state_set(BLE_LL_STATE_STANDBY);
+
+ /* May need to stop the rfclk */
+#ifdef BLE_XCVR_RFCLK
+ ble_ll_scan_rfclk_chk_stop();
+#endif
}
OS_EXIT_CRITICAL(sr);
}
@@ -757,6 +807,9 @@ ble_ll_scan_event_proc(struct os_event *ev)
uint32_t win_start;
uint32_t scan_itvl;
uint32_t next_event_time;
+#ifdef BLE_XCVR_RFCLK
+ uint32_t xtal_ticks;
+#endif
struct ble_ll_scan_sm *scansm;
/*
@@ -786,12 +839,19 @@ ble_ll_scan_event_proc(struct os_event *ev)
dt = now - win_start;
scansm->scan_chan = chan;
scansm->scan_win_start_time = win_start;
+ if (scansm->scan_window != scansm->scan_itvl) {
+ win = os_cputime_usecs_to_ticks(scansm->scan_window * BLE_HCI_SCAN_ITVL);
+ } else {
+ win = 0;
+ }
/* Determine on/off state based on scan window */
rxstate = 1;
next_event_time = win_start + scan_itvl;
- if (scansm->scan_window != scansm->scan_itvl) {
- win = os_cputime_usecs_to_ticks(scansm->scan_window * BLE_HCI_SCAN_ITVL);
+
+ OS_ENTER_CRITICAL(sr);
+
+ if (win != 0) {
if (dt >= win) {
rxstate = 0;
} else {
@@ -799,7 +859,6 @@ ble_ll_scan_event_proc(struct os_event *ev)
}
}
- OS_ENTER_CRITICAL(sr);
/*
* If we are not in the standby state it means that the scheduled
* scanning event was overlapped in the schedule. In this case all we do
@@ -815,6 +874,9 @@ ble_ll_scan_event_proc(struct os_event *ev)
case BLE_LL_STATE_SCANNING:
/* Must disable PHY since we will move to a new channel */
ble_phy_disable();
+ if (!rxstate) {
+ ble_ll_state_set(BLE_LL_STATE_STANDBY);
+ }
break;
case BLE_LL_STATE_STANDBY:
break;
@@ -822,11 +884,70 @@ ble_ll_scan_event_proc(struct os_event *ev)
assert(0);
break;
}
+
+#ifdef BLE_XCVR_RFCLK
+ if (rxstate == 0) {
+ /*
+ * We need to wake up before we need to start scanning in order
+ * to make sure the rfclock is on. If we are close to being on,
+ * enable the rfclock. If not, set wakeup time.
+ */
+ if (dt >= (scan_itvl - g_ble_ll_data.ll_xtal_ticks)) {
+ /* Start the clock if necessary */
+ if (start_scan) {
+ if (ble_ll_xcvr_rfclk_state() == BLE_RFCLK_STATE_OFF) {
+ ble_ll_xcvr_rfclk_start_now(now);
+ next_event_time = now + g_ble_ll_data.ll_xtal_ticks;
+ }
+ }
+ } else {
+ next_event_time -= g_ble_ll_data.ll_xtal_ticks;
+ if (start_scan) {
+ ble_ll_scan_rfclk_chk_stop();
+ }
+ }
+ }
+#endif
+
if (start_scan && rxstate) {
+#ifdef BLE_XCVR_RFCLK
+ /* NOTE: reuse rxstate */
+ rxstate = ble_ll_xcvr_rfclk_state();
+ if (rxstate != BLE_RFCLK_STATE_SETTLED) {
+ if (rxstate == BLE_RFCLK_STATE_OFF) {
+ xtal_ticks = g_ble_ll_data.ll_xtal_ticks;
+ } else {
+ xtal_ticks = ble_ll_xcvr_rfclk_time_till_settled();
+ }
+
+ /*
+ * Only bother if we have enough time to receive anything
+ * here. The next event time will turn off the clock.
+ */
+ if (win != 0) {
+ if ((win - dt) <= xtal_ticks) {
+ goto rfclk_not_settled;
+ }
+ }
+
+ /*
+ * If clock off, start clock. Set next event time to now plus
+ * the clock setting time.
+ */
+ if (rxstate == BLE_RFCLK_STATE_OFF) {
+ ble_ll_xcvr_rfclk_start_now(now);
+ }
+ next_event_time = now + xtal_ticks;
+ goto rfclk_not_settled;
+ }
+#endif
ble_ll_scan_start(scansm, scansm->scan_chan);
}
- OS_EXIT_CRITICAL(sr);
+#ifdef BLE_XCVR_RFCLK
+rfclk_not_settled:
+#endif
+ OS_EXIT_CRITICAL(sr);
os_cputime_timer_start(&scansm->scan_timer, next_event_time);
}
@@ -929,8 +1050,7 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
if (scansm->scan_rsp_pending) {
ble_ll_scan_req_backoff(scansm, 0);
}
- ble_phy_disable();
- ble_phy_rx();
+ ble_phy_restart_rx();
return 0;
}
@@ -1081,8 +1201,6 @@ ble_ll_scan_wfr_timer_exp(void)
{
struct ble_ll_scan_sm *scansm;
- ble_phy_disable();
-
/*
* If we timed out waiting for a response, the scan response pending
* flag should be set. Deal with scan backoff. Put device back into rx.
@@ -1091,7 +1209,8 @@ ble_ll_scan_wfr_timer_exp(void)
if (scansm->scan_rsp_pending) {
ble_ll_scan_req_backoff(scansm, 0);
}
- ble_phy_rx();
+
+ ble_phy_restart_rx();
}
/**
@@ -1480,7 +1599,7 @@ ble_ll_scan_init(void)
scansm->scan_itvl = BLE_HCI_SCAN_ITVL_DEF;
scansm->scan_window = BLE_HCI_SCAN_WINDOW_DEF;
- /* Initialize connection supervision timer */
+ /* Initialize scanning timer */
os_cputime_timer_init(&scansm->scan_timer, ble_ll_scan_timer_cb, scansm);
/* Get a scan request mbuf (packet header) and attach to state machine */
[5/5] incubator-mynewt-core git commit: The number of concurrent
connections should be default to 1.
Posted by we...@apache.org.
The number of concurrent connections should be default to 1.
Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/244227b7
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/244227b7
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/244227b7
Branch: refs/heads/develop
Commit: 244227b77eddce0a2a09034b436e5fafcf2815fb
Parents: 3c78595
Author: William San Filippo <wi...@runtime.io>
Authored: Thu Mar 30 13:59:58 2017 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Thu Mar 30 14:10:22 2017 -0700
----------------------------------------------------------------------
apps/bletest/src/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/244227b7/apps/bletest/src/main.c
----------------------------------------------------------------------
diff --git a/apps/bletest/src/main.c b/apps/bletest/src/main.c
index efb3fd4..e2519eb 100755
--- a/apps/bletest/src/main.c
+++ b/apps/bletest/src/main.c
@@ -172,7 +172,7 @@ bletest_multi_adv_instances[BLETEST_CFG_ADV_TEST_INSTANCES] = {
#define BLETEST_CFG_MAX_CE_LEN (BLETEST_CFG_CONN_ITVL)
#define BLETEST_CFG_CONN_PEER_ADDR_TYPE (BLE_HCI_CONN_PEER_ADDR_PUBLIC)
#define BLETEST_CFG_CONN_OWN_ADDR_TYPE (BLE_HCI_ADV_OWN_ADDR_PUBLIC)
-#define BLETEST_CFG_CONCURRENT_CONNS (8)
+#define BLETEST_CFG_CONCURRENT_CONNS (1)
/* Test packet config */
#define BLETEST_CFG_RAND_PKT_SIZE (1)