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 2016/04/28 01:47:05 UTC
[2/2] incubator-mynewt-core git commit: MYNEWT-85: Fix BLE timing for
start of connection events. MYNEWT-283: Slave anchor point now set correctly
on CRC error.
MYNEWT-85: Fix BLE timing for start of connection events.
MYNEWT-283: Slave anchor point now set correctly on CRC error.
Please read the respective tickets for a discussion of
the changes.
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/8ddc20ee
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/8ddc20ee
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/8ddc20ee
Branch: refs/heads/develop
Commit: 8ddc20eed045e5d9d0abe6b0bd5d6af83f872dcf
Parents: f04731b
Author: William San Filippo <wi...@runtime.io>
Authored: Wed Apr 27 16:45:17 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Wed Apr 27 16:46:54 2016 -0700
----------------------------------------------------------------------
apps/bletest/src/main.c | 39 +-
hw/mcu/nordic/nrf51xxx/src/hal_cputime.c | 225 +++++-----
hw/mcu/nordic/nrf52xxx/src/hal_cputime.c | 224 +++++-----
.../controller/include/controller/ble_ll.h | 5 +
.../controller/include/controller/ble_phy.h | 21 +-
net/nimble/controller/pkg.yml | 1 +
net/nimble/controller/src/ble_ll.c | 2 +-
net/nimble/controller/src/ble_ll_adv.c | 34 +-
net/nimble/controller/src/ble_ll_conn.c | 86 ++--
net/nimble/controller/src/ble_ll_scan.c | 3 +-
net/nimble/controller/src/ble_ll_sched.c | 1 +
net/nimble/drivers/native/src/ble_phy.c | 2 +-
net/nimble/drivers/nrf51/include/ble/xcvr.h | 32 ++
net/nimble/drivers/nrf51/src/ble_phy.c | 419 ++++++++++--------
net/nimble/drivers/nrf52/include/ble/xcvr.h | 32 ++
net/nimble/drivers/nrf52/src/ble_phy.c | 423 +++++++++++--------
net/nimble/include/nimble/ble.h | 2 +-
17 files changed, 882 insertions(+), 669 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8ddc20ee/apps/bletest/src/main.c
----------------------------------------------------------------------
diff --git a/apps/bletest/src/main.c b/apps/bletest/src/main.c
index 9510641..7218fd1 100755
--- a/apps/bletest/src/main.c
+++ b/apps/bletest/src/main.c
@@ -356,27 +356,30 @@ bletest_init_scanner(void)
{
int rc;
uint8_t dev_addr[BLE_DEV_ADDR_LEN];
+ uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_PARAM_LEN];
uint8_t filter_policy;
- /* Set scanning parameters */
- rc = bletest_hci_le_set_scan_params(BLETEST_CFG_SCAN_TYPE,
- BLETEST_CFG_SCAN_ITVL,
- BLETEST_CFG_SCAN_WINDOW,
- BLE_HCI_ADV_OWN_ADDR_PUBLIC,
- BLETEST_CFG_SCAN_FILT_POLICY);
+ rc = host_hci_cmd_build_le_set_scan_params(BLETEST_CFG_SCAN_TYPE,
+ BLETEST_CFG_SCAN_ITVL,
+ BLETEST_CFG_SCAN_WINDOW,
+ BLE_HCI_ADV_OWN_ADDR_PUBLIC,
+ BLETEST_CFG_SCAN_FILT_POLICY,
+ buf, sizeof buf);
assert(rc == 0);
-
- filter_policy = BLETEST_CFG_SCAN_FILT_POLICY;
- if (filter_policy & 1) {
- /* Add some whitelist addresses */
- dev_addr[0] = 0x00;
- dev_addr[1] = 0x00;
- dev_addr[2] = 0x00;
- dev_addr[3] = 0x88;
- dev_addr[4] = 0x88;
- dev_addr[5] = 0x08;
- rc = bletest_hci_le_add_to_whitelist(dev_addr, BLE_ADDR_TYPE_PUBLIC);
- assert(rc == 0);
+ rc = ble_hci_cmd_tx_empty_ack(buf);
+ if (rc == 0) {
+ filter_policy = BLETEST_CFG_SCAN_FILT_POLICY;
+ if (filter_policy & 1) {
+ /* Add some whitelist addresses */
+ dev_addr[0] = 0x00;
+ dev_addr[1] = 0x00;
+ dev_addr[2] = 0x00;
+ dev_addr[3] = 0x88;
+ dev_addr[4] = 0x88;
+ dev_addr[5] = 0x08;
+ rc = bletest_hci_le_add_to_whitelist(dev_addr, BLE_ADDR_TYPE_PUBLIC);
+ assert(rc == 0);
+ }
}
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8ddc20ee/hw/mcu/nordic/nrf51xxx/src/hal_cputime.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/nrf51xxx/src/hal_cputime.c b/hw/mcu/nordic/nrf51xxx/src/hal_cputime.c
index 2f1c4fa..eb12237 100644
--- a/hw/mcu/nordic/nrf51xxx/src/hal_cputime.c
+++ b/hw/mcu/nordic/nrf51xxx/src/hal_cputime.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,
@@ -16,6 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
+
#include <string.h>
#include <stdint.h>
#include <assert.h>
@@ -28,18 +29,15 @@
/* Maximum timer frequency */
#define NRF51_MAX_TIMER_FREQ (16000000)
-/*
- * Use these defines to select a timer and the compare channels. The reason
- * channel 2 is left open for TIMER0 is that there are pre-programmed PPI
- * channels that use timer 0 channel 2 for certain events. For example, the
- * radio has RADIO->EVENTS_END tied to capture channel 2. This can be
- * used to capture rx/tx end times.
- */
+#undef HAL_CPUTIME_USE_OVERFLOW
+/* The RF peripheral uses CC registers 0 and 1 for RF events. */
#define CPUTIMER NRF_TIMER0
#define CPUTIMER_IRQ (TIMER0_IRQn)
-#define CPUTIMER_CC_CNTR (0)
-#define CPUTIMER_CC_OVERFLOW (1)
+#define CPUTIMER_CC_CNTR (2)
+#ifdef HAL_CPUTIME_USE_OVERFLOW
+#define CPUTIMER_CC_OVERFLOW (2)
+#endif
#define CPUTIMER_CC_INT (3)
/* Interrupt mask for interrupt enable/clear */
@@ -73,12 +71,12 @@ cputime_disable_ocmp(void)
}
/**
- * cputime set ocmp
- *
- * Set the OCMP used by the cputime module to the desired cputime.
- *
- * NOTE: Must be called with interrupts disabled.
- *
+ * cputime set ocmp
+ *
+ * Set the OCMP used by the cputime module to the desired cputime.
+ *
+ * NOTE: Must be called with interrupts disabled.
+ *
* @param timer Pointer to timer.
*/
static void
@@ -103,12 +101,12 @@ cputime_set_ocmp(struct cpu_timer *timer)
}
/**
- * cputime chk expiration
- *
- * Iterates through the cputimer queue to determine if any timers have expired.
- * If the timer has expired the timer is removed from the queue and the timer
- * callback function is executed.
- *
+ * cputime chk expiration
+ *
+ * Iterates through the cputimer queue to determine if any timers have expired.
+ * If the timer has expired the timer is removed from the queue and the timer
+ * callback function is executed.
+ *
*/
static void
cputime_chk_expiration(void)
@@ -138,37 +136,38 @@ cputime_chk_expiration(void)
}
/**
- * cputime isr
- *
- * This is the global timer interrupt routine.
- *
+ * cputime isr
+ *
+ * This is the global timer interrupt routine.
+ *
*/
static void
cputime_isr(void)
{
uint32_t compare;
+#ifdef HAL_CPUTIME_USE_OVERFLOW
uint32_t overflow;
+#endif
/* Check interrupt source. If set, clear them */
compare = CPUTIMER->EVENTS_COMPARE[CPUTIMER_CC_INT];
if (compare) {
CPUTIMER->EVENTS_COMPARE[CPUTIMER_CC_INT] = 0;
}
+
+#ifdef HAL_CPUTIME_USE_OVERFLOW
overflow = CPUTIMER->EVENTS_COMPARE[CPUTIMER_CC_OVERFLOW];
if (overflow) {
CPUTIMER->EVENTS_COMPARE[CPUTIMER_CC_OVERFLOW] = 0;
+ ++g_cputime.uif_ints;
+ ++g_cputime.cputime_high;
}
+#endif
/* Count # of interrupts */
++g_cputime.timer_isrs;
- /* If overflow, increment high word of cpu time */
- if (overflow) {
- ++g_cputime.uif_ints;
- ++g_cputime.cputime_high;
- }
-
- /*
+ /*
* NOTE: we dont check the 'compare' variable here due to how the timer
* is implemented on this chip. There is no way to force an output
* compare, so if we are late setting the output compare (i.e. the timer
@@ -187,14 +186,14 @@ cputime_isr(void)
}
/**
- * cputime init
- *
- * Initialize the cputime module. This must be called after os_init is called
- * and before any other timer API are used. This should be called only once
- * and should be called before the hardware timer is used.
- *
+ * cputime init
+ *
+ * Initialize the cputime module. This must be called after os_init is called
+ * and before any other timer API are used. This should be called only once
+ * and should be called before the hardware timer is used.
+ *
* @param clock_freq The desired cputime frequency, in hertz (Hz).
- *
+ *
* @return int 0 on success; -1 on error.
*/
int
@@ -221,7 +220,7 @@ cputime_init(uint32_t clock_freq)
return -1;
}
- /*
+ /*
* Pre-scaler is 4 bits and is a 2^n, so the only possible values that
* work are 1, 2, 4, 8 and 16, which gives a valid pre-scaler of 0, 1, 2,
* 3 or 4.
@@ -276,9 +275,11 @@ cputime_init(uint32_t clock_freq)
CPUTIMER->TASKS_START = 1;
/* Use an output compare to generate an overflow */
+#ifdef HAL_CPUTIME_USE_OVERFLOW
CPUTIMER->CC[CPUTIMER_CC_OVERFLOW] = 0;
CPUTIMER->EVENTS_COMPARE[CPUTIMER_CC_OVERFLOW] = 0;
CPUTIMER->INTENSET = CPUTIMER_INT_MASK(CPUTIMER_CC_OVERFLOW);
+#endif
/* Set isr in vector table and enable interrupt */
NVIC_SetVector(CPUTIMER_IRQ, (uint32_t)cputime_isr);
@@ -291,12 +292,13 @@ cputime_init(uint32_t clock_freq)
/**
* cputime get64
- *
- * Returns cputime as a 64-bit number.
- *
+ *
+ * Returns cputime as a 64-bit number.
+ *
* @return uint64_t The 64-bit representation of cputime.
*/
-uint64_t
+#ifdef HAL_CPUTIME_USE_OVERFLOW
+uint64_t
cputime_get64(void)
{
uint32_t ctx;
@@ -317,12 +319,13 @@ cputime_get64(void)
return cpu_time;
}
+#endif
/**
- * cputime get32
- *
- * Returns the low 32 bits of cputime.
- *
+ * cputime get32
+ *
+ * Returns the low 32 bits of cputime.
+ *
* @return uint32_t The lower 32 bits of cputime
*/
uint32_t
@@ -338,15 +341,15 @@ cputime_get32(void)
}
/**
- * cputime nsecs to ticks
- *
- * Converts the given number of nanoseconds into cputime ticks.
- *
+ * cputime nsecs to ticks
+ *
+ * Converts the given number of nanoseconds into cputime ticks.
+ *
* @param usecs The number of nanoseconds to convert to ticks
- *
+ *
* @return uint32_t The number of ticks corresponding to 'nsecs'
*/
-uint32_t
+uint32_t
cputime_nsecs_to_ticks(uint32_t nsecs)
{
uint32_t ticks;
@@ -357,34 +360,34 @@ cputime_nsecs_to_ticks(uint32_t nsecs)
/**
* cputime ticks to nsecs
- *
- * Convert the given number of ticks into nanoseconds.
- *
+ *
+ * Convert the given number of ticks into nanoseconds.
+ *
* @param ticks The number of ticks to convert to nanoseconds.
- *
+ *
* @return uint32_t The number of nanoseconds corresponding to 'ticks'
*/
-uint32_t
+uint32_t
cputime_ticks_to_nsecs(uint32_t ticks)
{
uint32_t nsecs;
- nsecs = ((ticks * 1000) + (g_cputime.ticks_per_usec - 1)) /
+ nsecs = ((ticks * 1000) + (g_cputime.ticks_per_usec - 1)) /
g_cputime.ticks_per_usec;
return nsecs;
}
/**
- * cputime usecs to ticks
- *
- * Converts the given number of microseconds into cputime ticks.
- *
+ * 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
+uint32_t
cputime_usecs_to_ticks(uint32_t usecs)
{
uint32_t ticks;
@@ -395,14 +398,14 @@ cputime_usecs_to_ticks(uint32_t usecs)
/**
* cputime ticks to usecs
- *
- * Convert the given number of ticks into microseconds.
- *
+ *
+ * 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'
*/
-uint32_t
+uint32_t
cputime_ticks_to_usecs(uint32_t ticks)
{
uint32_t us;
@@ -413,12 +416,12 @@ cputime_ticks_to_usecs(uint32_t ticks)
/**
* cputime delay ticks
- *
- * Wait until the number of ticks has elapsed. This is a blocking delay.
- *
+ *
+ * Wait until the number of ticks has elapsed. This is a blocking delay.
+ *
* @param ticks The number of ticks to wait.
*/
-void
+void
cputime_delay_ticks(uint32_t ticks)
{
uint32_t until;
@@ -430,13 +433,13 @@ cputime_delay_ticks(uint32_t ticks)
}
/**
- * cputime delay nsecs
- *
- * Wait until 'nsecs' nanoseconds has elapsed. This is a blocking delay.
- *
+ * cputime delay nsecs
+ *
+ * Wait until 'nsecs' nanoseconds has elapsed. This is a blocking delay.
+ *
* @param nsecs The number of nanoseconds to wait.
*/
-void
+void
cputime_delay_nsecs(uint32_t nsecs)
{
uint32_t ticks;
@@ -446,13 +449,13 @@ cputime_delay_nsecs(uint32_t nsecs)
}
/**
- * cputime delay usecs
- *
- * Wait until 'usecs' microseconds has elapsed. This is a blocking delay.
- *
+ * cputime delay usecs
+ *
+ * Wait until 'usecs' microseconds has elapsed. This is a blocking delay.
+ *
* @param usecs The number of usecs to wait.
*/
-void
+void
cputime_delay_usecs(uint32_t usecs)
{
uint32_t ticks;
@@ -463,13 +466,13 @@ cputime_delay_usecs(uint32_t usecs)
/**
* cputime timer init
- *
- *
+ *
+ *
* @param timer The timer to initialize. Cannot be NULL.
* @param fp The timer callback function. Cannot be NULL.
- * @param arg Pointer to data object to pass to timer.
+ * @param arg Pointer to data object to pass to timer.
*/
-void
+void
cputime_timer_init(struct cpu_timer *timer, cputimer_func fp, void *arg)
{
assert(timer != NULL);
@@ -481,16 +484,16 @@ cputime_timer_init(struct cpu_timer *timer, cputimer_func fp, void *arg)
}
/**
- * cputime timer start
- *
- * Start a cputimer that will expire at 'cputime'. If cputime has already
- * passed, the timer callback will still be called (at interrupt context).
- * Cannot be called when the timer has already started.
- *
+ * cputime timer start
+ *
+ * Start a cputimer that will expire at 'cputime'. If cputime has already
+ * passed, the timer callback will still be called (at interrupt context).
+ * Cannot be called when the timer has already started.
+ *
* @param timer Pointer to timer to start. Cannot be NULL.
* @param cputime The cputime at which the timer should expire.
*/
-void
+void
cputime_timer_start(struct cpu_timer *timer, uint32_t cputime)
{
struct cpu_timer *entry;
@@ -508,7 +511,7 @@ cputime_timer_start(struct cpu_timer *timer, uint32_t cputime)
} else {
TAILQ_FOREACH(entry, &g_cputimer_q, link) {
if ((int32_t)(timer->cputime - entry->cputime) < 0) {
- TAILQ_INSERT_BEFORE(entry, timer, link);
+ TAILQ_INSERT_BEFORE(entry, timer, link);
break;
}
}
@@ -526,15 +529,15 @@ cputime_timer_start(struct cpu_timer *timer, uint32_t cputime)
}
/**
- * cputimer timer relative
- *
- * Sets a cpu timer that will expire 'usecs' microseconds from the current
- * cputime.
- *
+ * cputimer timer relative
+ *
+ * Sets a cpu timer that will expire 'usecs' microseconds from the current
+ * cputime.
+ *
* @param timer Pointer to timer. Cannot be NULL.
* @param usecs The number of usecs from now at which the timer will expire.
*/
-void
+void
cputime_timer_relative(struct cpu_timer *timer, uint32_t usecs)
{
uint32_t cputime;
@@ -546,15 +549,15 @@ cputime_timer_relative(struct cpu_timer *timer, uint32_t usecs)
}
/**
- * cputime timer stop
- *
- * Stops a cputimer from running. The timer is removed from the timer queue
- * and interrupts are disabled if no timers are left on the queue. Can be
- * called even if timer is not running.
- *
+ * cputime timer stop
+ *
+ * Stops a cputimer from running. The timer is removed from the timer queue
+ * and interrupts are disabled if no timers are left on the queue. Can be
+ * called even if timer is not running.
+ *
* @param timer Pointer to cputimer to stop. Cannot be NULL.
*/
-void
+void
cputime_timer_stop(struct cpu_timer *timer)
{
int reset_ocmp;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8ddc20ee/hw/mcu/nordic/nrf52xxx/src/hal_cputime.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_cputime.c b/hw/mcu/nordic/nrf52xxx/src/hal_cputime.c
index 134a601..fbcc96d 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_cputime.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_cputime.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,
@@ -29,18 +29,15 @@
/* Maximum timer frequency */
#define NRF52_MAX_TIMER_FREQ (16000000)
-/*
- * Use these defines to select a timer and the compare channels. The reason
- * channel 2 is left open for TIMER0 is that there are pre-programmed PPI
- * channels that use timer 0 channel 2 for certain events. For example, the
- * radio has RADIO->EVENTS_END tied to capture channel 2. This can be
- * used to capture rx/tx end times.
- */
+#undef HAL_CPUTIME_USE_OVERFLOW
+/* The RF peripheral uses CC registers 0 and 1 for RF events. */
#define CPUTIMER NRF_TIMER0
#define CPUTIMER_IRQ (TIMER0_IRQn)
-#define CPUTIMER_CC_CNTR (0)
-#define CPUTIMER_CC_OVERFLOW (1)
+#define CPUTIMER_CC_CNTR (2)
+#ifdef HAL_CPUTIME_USE_OVERFLOW
+#define CPUTIMER_CC_OVERFLOW (2)
+#endif
#define CPUTIMER_CC_INT (3)
/* Interrupt mask for interrupt enable/clear */
@@ -74,12 +71,12 @@ cputime_disable_ocmp(void)
}
/**
- * cputime set ocmp
- *
- * Set the OCMP used by the cputime module to the desired cputime.
- *
- * NOTE: Must be called with interrupts disabled.
- *
+ * cputime set ocmp
+ *
+ * Set the OCMP used by the cputime module to the desired cputime.
+ *
+ * NOTE: Must be called with interrupts disabled.
+ *
* @param timer Pointer to timer.
*/
static void
@@ -104,12 +101,12 @@ cputime_set_ocmp(struct cpu_timer *timer)
}
/**
- * cputime chk expiration
- *
- * Iterates through the cputimer queue to determine if any timers have expired.
- * If the timer has expired the timer is removed from the queue and the timer
- * callback function is executed.
- *
+ * cputime chk expiration
+ *
+ * Iterates through the cputimer queue to determine if any timers have expired.
+ * If the timer has expired the timer is removed from the queue and the timer
+ * callback function is executed.
+ *
*/
static void
cputime_chk_expiration(void)
@@ -139,37 +136,38 @@ cputime_chk_expiration(void)
}
/**
- * cputime isr
- *
- * This is the global timer interrupt routine.
- *
+ * cputime isr
+ *
+ * This is the global timer interrupt routine.
+ *
*/
static void
cputime_isr(void)
{
uint32_t compare;
+#ifdef HAL_CPUTIME_USE_OVERFLOW
uint32_t overflow;
+#endif
/* Check interrupt source. If set, clear them */
compare = CPUTIMER->EVENTS_COMPARE[CPUTIMER_CC_INT];
if (compare) {
CPUTIMER->EVENTS_COMPARE[CPUTIMER_CC_INT] = 0;
}
+
+#ifdef HAL_CPUTIME_USE_OVERFLOW
overflow = CPUTIMER->EVENTS_COMPARE[CPUTIMER_CC_OVERFLOW];
if (overflow) {
CPUTIMER->EVENTS_COMPARE[CPUTIMER_CC_OVERFLOW] = 0;
+ ++g_cputime.uif_ints;
+ ++g_cputime.cputime_high;
}
+#endif
/* Count # of interrupts */
++g_cputime.timer_isrs;
- /* If overflow, increment high word of cpu time */
- if (overflow) {
- ++g_cputime.uif_ints;
- ++g_cputime.cputime_high;
- }
-
- /*
+ /*
* NOTE: we dont check the 'compare' variable here due to how the timer
* is implemented on this chip. There is no way to force an output
* compare, so if we are late setting the output compare (i.e. the timer
@@ -188,14 +186,14 @@ cputime_isr(void)
}
/**
- * cputime init
- *
- * Initialize the cputime module. This must be called after os_init is called
- * and before any other timer API are used. This should be called only once
- * and should be called before the hardware timer is used.
- *
+ * cputime init
+ *
+ * Initialize the cputime module. This must be called after os_init is called
+ * and before any other timer API are used. This should be called only once
+ * and should be called before the hardware timer is used.
+ *
* @param clock_freq The desired cputime frequency, in hertz (Hz).
- *
+ *
* @return int 0 on success; -1 on error.
*/
int
@@ -222,7 +220,7 @@ cputime_init(uint32_t clock_freq)
return -1;
}
- /*
+ /*
* Pre-scaler is 4 bits and is a 2^n, so the only possible values that
* work are 1, 2, 4, 8 and 16, which gives a valid pre-scaler of 0, 1, 2,
* 3 or 4.
@@ -277,9 +275,11 @@ cputime_init(uint32_t clock_freq)
CPUTIMER->TASKS_START = 1;
/* Use an output compare to generate an overflow */
+#ifdef HAL_CPUTIME_USE_OVERFLOW
CPUTIMER->CC[CPUTIMER_CC_OVERFLOW] = 0;
CPUTIMER->EVENTS_COMPARE[CPUTIMER_CC_OVERFLOW] = 0;
CPUTIMER->INTENSET = CPUTIMER_INT_MASK(CPUTIMER_CC_OVERFLOW);
+#endif
/* Set isr in vector table and enable interrupt */
NVIC_SetVector(CPUTIMER_IRQ, (uint32_t)cputime_isr);
@@ -292,12 +292,13 @@ cputime_init(uint32_t clock_freq)
/**
* cputime get64
- *
- * Returns cputime as a 64-bit number.
- *
+ *
+ * Returns cputime as a 64-bit number.
+ *
* @return uint64_t The 64-bit representation of cputime.
*/
-uint64_t
+#ifdef HAL_CPUTIME_USE_OVERFLOW
+uint64_t
cputime_get64(void)
{
uint32_t ctx;
@@ -318,12 +319,13 @@ cputime_get64(void)
return cpu_time;
}
+#endif
/**
- * cputime get32
- *
- * Returns the low 32 bits of cputime.
- *
+ * cputime get32
+ *
+ * Returns the low 32 bits of cputime.
+ *
* @return uint32_t The lower 32 bits of cputime
*/
uint32_t
@@ -339,15 +341,15 @@ cputime_get32(void)
}
/**
- * cputime nsecs to ticks
- *
- * Converts the given number of nanoseconds into cputime ticks.
- *
+ * cputime nsecs to ticks
+ *
+ * Converts the given number of nanoseconds into cputime ticks.
+ *
* @param usecs The number of nanoseconds to convert to ticks
- *
+ *
* @return uint32_t The number of ticks corresponding to 'nsecs'
*/
-uint32_t
+uint32_t
cputime_nsecs_to_ticks(uint32_t nsecs)
{
uint32_t ticks;
@@ -358,34 +360,34 @@ cputime_nsecs_to_ticks(uint32_t nsecs)
/**
* cputime ticks to nsecs
- *
- * Convert the given number of ticks into nanoseconds.
- *
+ *
+ * Convert the given number of ticks into nanoseconds.
+ *
* @param ticks The number of ticks to convert to nanoseconds.
- *
+ *
* @return uint32_t The number of nanoseconds corresponding to 'ticks'
*/
-uint32_t
+uint32_t
cputime_ticks_to_nsecs(uint32_t ticks)
{
uint32_t nsecs;
- nsecs = ((ticks * 1000) + (g_cputime.ticks_per_usec - 1)) /
+ nsecs = ((ticks * 1000) + (g_cputime.ticks_per_usec - 1)) /
g_cputime.ticks_per_usec;
return nsecs;
}
/**
- * cputime usecs to ticks
- *
- * Converts the given number of microseconds into cputime ticks.
- *
+ * 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
+uint32_t
cputime_usecs_to_ticks(uint32_t usecs)
{
uint32_t ticks;
@@ -396,14 +398,14 @@ cputime_usecs_to_ticks(uint32_t usecs)
/**
* cputime ticks to usecs
- *
- * Convert the given number of ticks into microseconds.
- *
+ *
+ * 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'
*/
-uint32_t
+uint32_t
cputime_ticks_to_usecs(uint32_t ticks)
{
uint32_t us;
@@ -414,12 +416,12 @@ cputime_ticks_to_usecs(uint32_t ticks)
/**
* cputime delay ticks
- *
- * Wait until the number of ticks has elapsed. This is a blocking delay.
- *
+ *
+ * Wait until the number of ticks has elapsed. This is a blocking delay.
+ *
* @param ticks The number of ticks to wait.
*/
-void
+void
cputime_delay_ticks(uint32_t ticks)
{
uint32_t until;
@@ -431,13 +433,13 @@ cputime_delay_ticks(uint32_t ticks)
}
/**
- * cputime delay nsecs
- *
- * Wait until 'nsecs' nanoseconds has elapsed. This is a blocking delay.
- *
+ * cputime delay nsecs
+ *
+ * Wait until 'nsecs' nanoseconds has elapsed. This is a blocking delay.
+ *
* @param nsecs The number of nanoseconds to wait.
*/
-void
+void
cputime_delay_nsecs(uint32_t nsecs)
{
uint32_t ticks;
@@ -447,13 +449,13 @@ cputime_delay_nsecs(uint32_t nsecs)
}
/**
- * cputime delay usecs
- *
- * Wait until 'usecs' microseconds has elapsed. This is a blocking delay.
- *
+ * cputime delay usecs
+ *
+ * Wait until 'usecs' microseconds has elapsed. This is a blocking delay.
+ *
* @param usecs The number of usecs to wait.
*/
-void
+void
cputime_delay_usecs(uint32_t usecs)
{
uint32_t ticks;
@@ -464,13 +466,13 @@ cputime_delay_usecs(uint32_t usecs)
/**
* cputime timer init
- *
- *
+ *
+ *
* @param timer The timer to initialize. Cannot be NULL.
* @param fp The timer callback function. Cannot be NULL.
- * @param arg Pointer to data object to pass to timer.
+ * @param arg Pointer to data object to pass to timer.
*/
-void
+void
cputime_timer_init(struct cpu_timer *timer, cputimer_func fp, void *arg)
{
assert(timer != NULL);
@@ -482,16 +484,16 @@ cputime_timer_init(struct cpu_timer *timer, cputimer_func fp, void *arg)
}
/**
- * cputime timer start
- *
- * Start a cputimer that will expire at 'cputime'. If cputime has already
- * passed, the timer callback will still be called (at interrupt context).
- * Cannot be called when the timer has already started.
- *
+ * cputime timer start
+ *
+ * Start a cputimer that will expire at 'cputime'. If cputime has already
+ * passed, the timer callback will still be called (at interrupt context).
+ * Cannot be called when the timer has already started.
+ *
* @param timer Pointer to timer to start. Cannot be NULL.
* @param cputime The cputime at which the timer should expire.
*/
-void
+void
cputime_timer_start(struct cpu_timer *timer, uint32_t cputime)
{
struct cpu_timer *entry;
@@ -509,7 +511,7 @@ cputime_timer_start(struct cpu_timer *timer, uint32_t cputime)
} else {
TAILQ_FOREACH(entry, &g_cputimer_q, link) {
if ((int32_t)(timer->cputime - entry->cputime) < 0) {
- TAILQ_INSERT_BEFORE(entry, timer, link);
+ TAILQ_INSERT_BEFORE(entry, timer, link);
break;
}
}
@@ -527,15 +529,15 @@ cputime_timer_start(struct cpu_timer *timer, uint32_t cputime)
}
/**
- * cputimer timer relative
- *
- * Sets a cpu timer that will expire 'usecs' microseconds from the current
- * cputime.
- *
+ * cputimer timer relative
+ *
+ * Sets a cpu timer that will expire 'usecs' microseconds from the current
+ * cputime.
+ *
* @param timer Pointer to timer. Cannot be NULL.
* @param usecs The number of usecs from now at which the timer will expire.
*/
-void
+void
cputime_timer_relative(struct cpu_timer *timer, uint32_t usecs)
{
uint32_t cputime;
@@ -547,15 +549,15 @@ cputime_timer_relative(struct cpu_timer *timer, uint32_t usecs)
}
/**
- * cputime timer stop
- *
- * Stops a cputimer from running. The timer is removed from the timer queue
- * and interrupts are disabled if no timers are left on the queue. Can be
- * called even if timer is not running.
- *
+ * cputime timer stop
+ *
+ * Stops a cputimer from running. The timer is removed from the timer queue
+ * and interrupts are disabled if no timers are left on the queue. Can be
+ * called even if timer is not running.
+ *
* @param timer Pointer to cputimer to stop. Cannot be NULL.
*/
-void
+void
cputime_timer_stop(struct cpu_timer *timer)
{
int reset_ocmp;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8ddc20ee/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 60a8408..e579a26 100644
--- a/net/nimble/controller/include/controller/ble_ll.h
+++ b/net/nimble/controller/include/controller/ble_ll.h
@@ -201,6 +201,9 @@ struct ble_dev_addr
*/
#define BLE_TX_DUR_USECS_M(len) (((len) + BLE_LL_PDU_OVERHEAD) << 3)
+/* Calculates the time it takes to transmit 'len' bytes */
+#define BLE_TX_LEN_USECS_M(len) ((len) << 3)
+
/* Access address for advertising channels */
#define BLE_ACCESS_ADDR_ADV (0x8E89BED6)
@@ -373,6 +376,8 @@ int ble_ll_rand_start(void);
#define BLE_LL_LOG_ID_RX_END (3)
#define BLE_LL_LOG_ID_WFR_EXP (4)
#define BLE_LL_LOG_ID_PHY_TXEND (5)
+#define BLE_LL_LOG_ID_PHY_TX (6)
+#define BLE_LL_LOG_ID_PHY_RX (7)
#define BLE_LL_LOG_ID_PHY_DISABLE (9)
#define BLE_LL_LOG_ID_CONN_EV_START (10)
#define BLE_LL_LOG_ID_CONN_TX (15)
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8ddc20ee/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 88373c2..af31dbd 100644
--- a/net/nimble/controller/include/controller/ble_phy.h
+++ b/net/nimble/controller/include/controller/ble_phy.h
@@ -23,18 +23,6 @@
/* Forward declarations */
struct os_mbuf;
-/*
- * XXX: Transceiver definitions. These dont belong here and will be moved
- * once we finalize transceiver specific support.
- */
-#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 \
- (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
-
/* Channel/Frequency defintions */
#define BLE_PHY_NUM_CHANS (40)
#define BLE_PHY_NUM_DATA_CHANS (37)
@@ -77,6 +65,7 @@ struct os_mbuf;
#define BLE_PHY_ERR_INIT (2)
#define BLE_PHY_ERR_INV_PARAM (3)
#define BLE_PHY_ERR_NO_BUFS (4)
+#define BLE_PHY_ERR_TX_LATE (5)
/* Maximun PDU length. Includes LL header of 2 bytes and 255 bytes payload. */
#define BLE_PHY_MAX_PDU_LEN (257)
@@ -93,11 +82,17 @@ int ble_phy_reset(void);
/* Set the PHY channel */
int ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit);
+/* Set transmit start time */
+int ble_phy_tx_set_start_time(uint32_t cputime);
+
+/* Set receive start time */
+int ble_phy_rx_set_start_time(uint32_t cputime);
+
/* Set the transmit end callback and argument */
void ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg);
/* Place the PHY into transmit mode */
-int ble_phy_tx(struct os_mbuf *txpdu, uint8_t beg_trans, uint8_t end_trans);
+int ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans);
/* Place the PHY into receive mode */
int ble_phy_rx(void);
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8ddc20ee/net/nimble/controller/pkg.yml
----------------------------------------------------------------------
diff --git a/net/nimble/controller/pkg.yml b/net/nimble/controller/pkg.yml
index f9c3eae..07a9d56 100644
--- a/net/nimble/controller/pkg.yml
+++ b/net/nimble/controller/pkg.yml
@@ -25,6 +25,7 @@ pkg.keywords:
- ble
- bluetooth
+pkg.req_apis: ble_driver
pkg.deps:
- libs/os
- sys/stats
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8ddc20ee/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 003d594..a5ba967 100644
--- a/net/nimble/controller/src/ble_ll.c
+++ b/net/nimble/controller/src/ble_ll.c
@@ -737,7 +737,7 @@ ble_ll_rx_end(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *ble_hdr)
ble_ll_log(BLE_LL_LOG_ID_RX_END, rxbuf[0],
((uint16_t)ble_hdr->rxinfo.flags << 8) | rxbuf[1],
- (BLE_MBUF_HDR_PTR(rxpdu))->end_cputime);
+ (BLE_MBUF_HDR_PTR(rxpdu))->beg_cputime);
/* Check channel type */
if (chan < BLE_PHY_NUM_DATA_CHANS) {
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8ddc20ee/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 d6a208a..4d45f16 100644
--- a/net/nimble/controller/src/ble_ll_adv.c
+++ b/net/nimble/controller/src/ble_ll_adv.c
@@ -21,6 +21,7 @@
#include <assert.h>
#include "os/os.h"
#include "bsp/bsp.h"
+#include "ble/xcvr.h"
#include "nimble/ble.h"
#include "nimble/nimble_opt.h"
#include "nimble/hci_common.h"
@@ -343,7 +344,7 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch)
{
int rc;
uint8_t end_trans;
- uint32_t start_time;
+ uint32_t txstart;
struct ble_ll_adv_sm *advsm;
/* Get the state machine for the event */
@@ -353,6 +354,15 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch)
rc = ble_phy_setchan(advsm->adv_chan, 0, 0);
assert(rc == 0);
+ /* Set transmit start time. */
+ txstart = sch->start_time + XCVR_PROC_DELAY_USECS;
+ rc = ble_phy_tx_set_start_time(txstart);
+ if (rc) {
+ STATS_INC(ble_ll_stats, adv_late_starts);
+ ble_ll_adv_tx_done(advsm);
+ return BLE_LL_SCHED_STATE_DONE;
+ }
+
#ifdef BLE_LL_CFG_FEAT_LE_ENCRYPTION
ble_phy_encrypt_disable();
#endif
@@ -366,23 +376,12 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch)
ble_phy_set_txend_cb(NULL, NULL);
}
- /* This is for debug */
- start_time = cputime_get32();
-
- /* XXX: transmit using an output compare */
/* Transmit advertisement */
- rc = ble_phy_tx(advsm->adv_pdu, BLE_PHY_TRANSITION_NONE, end_trans);
+ rc = ble_phy_tx(advsm->adv_pdu, end_trans);
if (rc) {
- /* Transmit failed. */
ble_ll_adv_tx_done(advsm);
rc = BLE_LL_SCHED_STATE_DONE;
} else {
- /* Check if we were late getting here */
- if ((int32_t)(start_time - (advsm->adv_pdu_start_time -
- cputime_usecs_to_ticks(XCVR_TX_START_DELAY_USECS))) > 0) {
- STATS_INC(ble_ll_stats, adv_late_starts);
- }
-
/* Enable/disable whitelisting based on filter policy */
if (advsm->adv_filter_policy != BLE_HCI_ADV_FILT_NONE) {
ble_ll_whitelist_enable();
@@ -878,8 +877,7 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu)
rc = -1;
if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) {
ble_phy_set_txend_cb(ble_ll_adv_tx_done, &g_ble_ll_adv_sm);
- rc = ble_phy_tx(advsm->scan_rsp_pdu, BLE_PHY_TRANSITION_RX_TX,
- BLE_PHY_TRANSITION_NONE);
+ rc = ble_phy_tx(advsm->scan_rsp_pdu, BLE_PHY_TRANSITION_NONE);
if (!rc) {
ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_SCAN_RSP_TXD;
STATS_INC(ble_ll_stats, scan_rsp_txg);
@@ -903,7 +901,9 @@ int
ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr)
{
int valid;
+ uint8_t pyld_len;
uint8_t *inita;
+ uint32_t endtime;
struct ble_ll_adv_sm *advsm;
/* Check filter policy. */
@@ -937,7 +937,9 @@ ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr)
if (valid) {
/* Try to start slave connection. If successful, stop advertising */
- valid = ble_ll_conn_slave_start(rxbuf, hdr->end_cputime);
+ pyld_len = rxbuf[1] & BLE_ADV_PDU_HDR_LEN_MASK;
+ endtime = hdr->beg_cputime + BLE_TX_DUR_USECS_M(pyld_len);
+ valid = ble_ll_conn_slave_start(rxbuf, endtime);
if (valid) {
ble_ll_adv_sm_stop(advsm);
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8ddc20ee/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 05b2c6c..07e7fad 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -25,6 +25,7 @@
#include "nimble/ble.h"
#include "nimble/nimble_opt.h"
#include "nimble/hci_common.h"
+#include "ble/xcvr.h"
#include "controller/ble_ll.h"
#include "controller/ble_ll_hci.h"
#include "controller/ble_ll_scan.h"
@@ -740,7 +741,7 @@ ble_ll_conn_chk_csm_flags(struct ble_ll_conn_sm *connsm)
* @return int 0: success; otherwise failure to transmit
*/
static int
-ble_ll_conn_tx_data_pdu(struct ble_ll_conn_sm *connsm, int beg_transition)
+ble_ll_conn_tx_data_pdu(struct ble_ll_conn_sm *connsm)
{
int rc;
uint8_t md;
@@ -1049,7 +1050,7 @@ conn_tx_pdu:
/* Set transmit end callback */
ble_phy_set_txend_cb(txend_func, connsm);
- rc = ble_phy_tx(m, beg_transition, end_transition);
+ rc = ble_phy_tx(m, end_transition);
if (!rc) {
/* Log transmit on connection state */
cur_txlen = ble_hdr->txinfo.pyld_len;
@@ -1115,21 +1116,28 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch)
connsm->crcinit);
if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
+ /* Set start time of transmission */
+ rc = ble_phy_tx_set_start_time(sch->start_time + XCVR_PROC_DELAY_USECS);
+ if (!rc) {
#ifdef BLE_LL_CFG_FEAT_LE_ENCRYPTION
- if (CONN_F_ENCRYPTED(connsm)) {
- ble_phy_encrypt_enable(connsm->enc_data.tx_pkt_cntr,
- connsm->enc_data.iv,
- connsm->enc_data.enc_block.cipher_text,
- 1);
- } else {
- ble_phy_encrypt_disable();
- }
+ if (CONN_F_ENCRYPTED(connsm)) {
+ ble_phy_encrypt_enable(connsm->enc_data.tx_pkt_cntr,
+ connsm->enc_data.iv,
+ connsm->enc_data.enc_block.cipher_text,
+ 1);
+ } else {
+ ble_phy_encrypt_disable();
+ }
#endif
- rc = ble_ll_conn_tx_data_pdu(connsm, BLE_PHY_TRANSITION_NONE);
- if (!rc) {
- rc = BLE_LL_SCHED_STATE_RUNNING;
+ rc = ble_ll_conn_tx_data_pdu(connsm);
+ if (!rc) {
+ rc = BLE_LL_SCHED_STATE_RUNNING;
+ } else {
+ /* Inform LL task of connection event end */
+ rc = BLE_LL_SCHED_STATE_DONE;
+ }
} else {
- /* Inform LL task of connection event end */
+ STATS_INC(ble_ll_conn_stats, conn_ev_late);
rc = BLE_LL_SCHED_STATE_DONE;
}
} else {
@@ -1143,6 +1151,10 @@ 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.
+ */
rc = ble_phy_rx();
if (rc) {
/* End the connection event as we have no more buffers */
@@ -1938,7 +1950,7 @@ ble_ll_conn_request_send(uint8_t addr_type, uint8_t *adva, uint16_t txoffset)
m = ble_ll_scan_get_pdu();
ble_ll_conn_req_pdu_update(m, adva, addr_type, txoffset);
ble_phy_set_txend_cb(ble_ll_conn_req_txend, NULL);
- rc = ble_phy_tx(m, BLE_PHY_TRANSITION_RX_TX, BLE_PHY_TRANSITION_NONE);
+ rc = ble_phy_tx(m, BLE_PHY_TRANSITION_NONE);
return rc;
}
@@ -1973,6 +1985,8 @@ void
ble_ll_init_rx_pkt_in(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr)
{
uint8_t addr_type;
+ uint8_t payload_len;
+ uint32_t endtime;
struct ble_ll_conn_sm *connsm;
/* Get the connection state machine we are trying to create */
@@ -2002,7 +2016,9 @@ 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);
- ble_ll_conn_created(connsm, ble_hdr->end_cputime);
+ payload_len = rxbuf[1] & BLE_ADV_PDU_HDR_LEN_MASK;;
+ endtime = ble_hdr->beg_cputime + BLE_TX_DUR_USECS_M(payload_len);
+ ble_ll_conn_created(connsm, endtime);
} else {
ble_ll_scan_chk_resume();
}
@@ -2030,6 +2046,8 @@ ble_ll_init_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
uint8_t *adv_addr;
uint8_t *init_addr;
uint8_t *rxbuf;
+ uint8_t pyld_len;
+ uint32_t endtime;
struct ble_mbuf_hdr *ble_hdr;
/*
@@ -2049,6 +2067,7 @@ ble_ll_init_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
/* Only interested in ADV IND or ADV DIRECT IND */
rxbuf = rxpdu->om_data;
pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK;
+ pyld_len = rxbuf[1] & BLE_ADV_PDU_HDR_LEN_MASK;
switch (pdu_type) {
case BLE_ADV_PDU_TYPE_ADV_IND:
@@ -2098,8 +2117,8 @@ ble_ll_init_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
}
/* Attempt to schedule new connection. Possible that this might fail */
- if (!ble_ll_sched_master_new(g_ble_ll_conn_create_sm,
- ble_hdr->end_cputime,
+ endtime = ble_hdr->beg_cputime + BLE_TX_DUR_USECS_M(pyld_len);
+ if (!ble_ll_sched_master_new(g_ble_ll_conn_create_sm, endtime,
NIMBLE_OPT_LL_CONN_INIT_SLOTS)) {
/* Setup to transmit the connect request */
rc = ble_ll_conn_request_send(addr_type, adv_addr,
@@ -2339,7 +2358,8 @@ ble_ll_conn_rx_isr_end(struct os_mbuf *rxpdu, uint32_t aa)
uint8_t reply;
uint8_t rem_bytes;
uint8_t opcode;
- uint32_t ticks;
+ uint8_t pyld_len;
+ uint32_t endtime;
struct os_mbuf *txpdu;
struct ble_ll_conn_sm *connsm;
struct ble_mbuf_hdr *rxhdr;
@@ -2365,6 +2385,8 @@ ble_ll_conn_rx_isr_end(struct os_mbuf *rxpdu, uint32_t aa)
/* Set the handle in the ble mbuf header */
rxhdr = BLE_MBUF_HDR_PTR(rxpdu);
rxhdr->rxinfo.handle = connsm->conn_handle;
+ hdr_byte = rxpdu->om_data[0];
+ pyld_len = rxpdu->om_data[1];
/*
* Check the packet CRC. A connection event can continue even if the
@@ -2391,9 +2413,6 @@ ble_ll_conn_rx_isr_end(struct os_mbuf *rxpdu, uint32_t aa)
/* Reset consecutively received bad crcs (since this one was good!) */
connsm->cons_rxd_bad_crc = 0;
- /* Store received header byte in state machine */
- hdr_byte = rxpdu->om_data[0];
-
/* Check for valid LLID before proceeding. */
if ((hdr_byte & BLE_LL_DATA_HDR_LLID_MASK) == 0) {
/*
@@ -2534,7 +2553,8 @@ chk_rx_terminate_ind:
/* If reply flag set, send data pdu and continue connection event */
rc = -1;
- if (reply && ble_ll_conn_can_send_next_pdu(connsm, rxhdr->end_cputime)) {
+ endtime = rxhdr->beg_cputime + BLE_TX_DUR_USECS_M(pyld_len);
+ if (reply && ble_ll_conn_can_send_next_pdu(connsm, endtime)) {
/*
* While this is not perfect, we will just check to see if the
* terminate timer will expire within two packet times. If it will,
@@ -2544,28 +2564,22 @@ chk_rx_terminate_ind:
* XXX: should we just skip this check?
*/
if (IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_TERMINATE)) {
- ticks = BLE_TX_DUR_USECS_M(0) +
- BLE_TX_DUR_USECS_M(BLE_LL_CTRL_TERMINATE_IND_LEN + 1) +
- BLE_LL_IFS;
- ticks = cputime_usecs_to_ticks(ticks) + cputime_get32();
- if ((int32_t)(connsm->terminate_timeout - ticks) < 0) {
+ endtime = BLE_TX_DUR_USECS_M(BLE_LL_CTRL_TERMINATE_IND_LEN + 1) +
+ BLE_TX_DUR_USECS_M(0) + BLE_LL_IFS;
+ endtime = cputime_usecs_to_ticks(endtime) + cputime_get32();
+ if ((int32_t)(connsm->terminate_timeout - endtime) < 0) {
goto conn_rx_pdu_end;
}
}
- rc = ble_ll_conn_tx_data_pdu(connsm, BLE_PHY_TRANSITION_RX_TX);
+ rc = ble_ll_conn_tx_data_pdu(connsm);
}
conn_rx_pdu_end:
/* Set anchor point (and last) if 1st received frame in connection event */
if (connsm->csmflags.cfbit.slave_set_last_anchor) {
connsm->csmflags.cfbit.slave_set_last_anchor = 0;
- /* XXX: For now, we just wont adjust the anchor point on crc error
- until I fix this issue */
- if (BLE_MBUF_HDR_CRC_OK(rxhdr)) {
- connsm->last_anchor_point = rxhdr->end_cputime -
- cputime_usecs_to_ticks(BLE_TX_DUR_USECS_M(rxpdu->om_data[1]));
- connsm->anchor_point = connsm->last_anchor_point;
- }
+ connsm->last_anchor_point = rxhdr->beg_cputime;
+ connsm->anchor_point = connsm->last_anchor_point;
}
/* Send link layer a connection end event if over */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8ddc20ee/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 dbcc63a..94a33e3 100644
--- a/net/nimble/controller/src/ble_ll_scan.c
+++ b/net/nimble/controller/src/ble_ll_scan.c
@@ -915,8 +915,7 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
if (scansm->backoff_count == 0) {
/* Setup to transmit the scan request */
ble_ll_scan_req_pdu_make(scansm, adv_addr, addr_type);
- rc = ble_phy_tx(scansm->scan_req_pdu, BLE_PHY_TRANSITION_RX_TX,
- BLE_PHY_TRANSITION_TX_RX);
+ rc = ble_phy_tx(scansm->scan_req_pdu, BLE_PHY_TRANSITION_TX_RX);
/* Set "waiting for scan response" flag */
scansm->scan_rsp_pending = 1;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8ddc20ee/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 9b0ccea..82f4189 100644
--- a/net/nimble/controller/src/ble_ll_sched.c
+++ b/net/nimble/controller/src/ble_ll_sched.c
@@ -20,6 +20,7 @@
#include <assert.h>
#include <string.h>
#include "os/os.h"
+#include "ble/xcvr.h"
#include "controller/ble_phy.h"
#include "controller/ble_ll.h"
#include "controller/ble_ll_sched.h"
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8ddc20ee/net/nimble/drivers/native/src/ble_phy.c
----------------------------------------------------------------------
diff --git a/net/nimble/drivers/native/src/ble_phy.c b/net/nimble/drivers/native/src/ble_phy.c
index 3cdca69..4b132ca 100644
--- a/net/nimble/drivers/native/src/ble_phy.c
+++ b/net/nimble/drivers/native/src/ble_phy.c
@@ -257,7 +257,7 @@ ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg)
}
int
-ble_phy_tx(struct os_mbuf *txpdu, uint8_t beg_trans, uint8_t end_trans)
+ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans)
{
int rc;
uint32_t state;
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8ddc20ee/net/nimble/drivers/nrf51/include/ble/xcvr.h
----------------------------------------------------------------------
diff --git a/net/nimble/drivers/nrf51/include/ble/xcvr.h b/net/nimble/drivers/nrf51/include/ble/xcvr.h
new file mode 100644
index 0000000..34abd7a
--- /dev/null
+++ b/net/nimble/drivers/nrf51/include/ble/xcvr.h
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_BLE_XCVR_
+#define H_BLE_XCVR_
+
+/* Transceiver specific defintions */
+#define XCVR_RX_START_DELAY_USECS (140)
+#define XCVR_TX_START_DELAY_USECS (140)
+#define XCVR_PROC_DELAY_USECS (100)
+#define XCVR_TX_SCHED_DELAY_USECS \
+ (XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+#define XCVR_RX_SCHED_DELAY_USECS \
+ (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+
+#endif /* H_BLE_XCVR_ */
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8ddc20ee/net/nimble/drivers/nrf51/src/ble_phy.c
----------------------------------------------------------------------
diff --git a/net/nimble/drivers/nrf51/src/ble_phy.c b/net/nimble/drivers/nrf51/src/ble_phy.c
index d95329a..70a7500 100644
--- a/net/nimble/drivers/nrf51/src/ble_phy.c
+++ b/net/nimble/drivers/nrf51/src/ble_phy.c
@@ -61,6 +61,7 @@
/* Maximum length of frames */
#define NRF_MAXLEN (255)
#define NRF_BALEN (3) /* For base address of 3 bytes */
+#define NRF_RX_START_OFFSET (5)
/* Maximum tx power */
#define NRF_TX_PWR_MAX_DBM (4)
@@ -76,6 +77,7 @@ struct ble_phy_obj
uint8_t phy_transition;
uint8_t phy_rx_started;
uint8_t phy_encrypted;
+ uint8_t phy_tx_pyld_len;
uint32_t phy_access_address;
struct os_mbuf *rxpdu;
void *txend_arg;
@@ -102,6 +104,7 @@ STATS_SECT_START(ble_phy_stats)
STATS_SECT_ENTRY(rx_aborts)
STATS_SECT_ENTRY(rx_valid)
STATS_SECT_ENTRY(rx_crc_err)
+ STATS_SECT_ENTRY(rx_late)
STATS_SECT_ENTRY(no_bufs)
STATS_SECT_ENTRY(radio_state_errs)
STATS_SECT_ENTRY(rx_hw_err)
@@ -119,6 +122,7 @@ STATS_NAME_START(ble_phy_stats)
STATS_NAME(ble_phy_stats, rx_aborts)
STATS_NAME(ble_phy_stats, rx_valid)
STATS_NAME(ble_phy_stats, rx_crc_err)
+ STATS_NAME(ble_phy_stats, rx_late)
STATS_NAME(ble_phy_stats, no_bufs)
STATS_NAME(ble_phy_stats, radio_state_errs)
STATS_NAME(ble_phy_stats, rx_hw_err)
@@ -250,6 +254,9 @@ ble_phy_rx_xcvr_setup(void)
NRF_RADIO->PACKETPTR = (uint32_t)g_ble_phy_data.rxpdu->om_data;
#endif
+ /* We dont want to trigger TXEN on output compare match */
+ NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk;
+
/* Reset the rx started flag. Used for the wait for response */
g_ble_phy_data.phy_rx_started = 0;
g_ble_phy_data.phy_state = BLE_PHY_STATE_RX;
@@ -285,7 +292,7 @@ ble_phy_tx_end_isr(void)
/* Log the event */
ble_ll_log(BLE_LL_LOG_ID_PHY_TXEND, (g_ble_phy_txrx_buf[0] >> 8) & 0xFF,
- g_ble_phy_data.phy_encrypted, NRF_TIMER0->CC[2]);
+ g_ble_phy_data.phy_encrypted, NRF_TIMER0->CC[1]);
/* Clear events and clear interrupt on disabled event */
NRF_RADIO->EVENTS_DISABLED = 0;
@@ -318,14 +325,16 @@ ble_phy_tx_end_isr(void)
}
/*
- * Enable the wait for response timer. Note that cc #2 on
- * timer 0 contains the transmit end time
+ * Enable the wait for response timer. Note that cc #1 on
+ * timer 0 contains the transmit start time
*/
- wfr_time = NRF_TIMER0->CC[2];
+ wfr_time = NRF_TIMER0->CC[1] - BLE_TX_LEN_USECS_M(NRF_RX_START_OFFSET);
+ wfr_time += BLE_TX_DUR_USECS_M(g_ble_phy_data.phy_tx_pyld_len);
wfr_time += cputime_usecs_to_ticks(BLE_LL_WFR_USECS);
ble_ll_wfr_enable(wfr_time);
} else {
- /* Better not be going from rx to tx! */
+ /* Disable automatic TXEN */
+ NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk;
assert(transition == BLE_PHY_TRANSITION_NONE);
}
@@ -336,152 +345,170 @@ ble_phy_tx_end_isr(void)
}
static void
-ble_phy_isr(void)
+ble_phy_rx_end_isr(void)
{
int rc;
- uint8_t crcok;
- uint32_t irq_en;
- uint32_t state;
#ifdef BLE_LL_CFG_FEAT_LE_ENCRYPTION
uint8_t *dptr;
#endif
+ uint8_t crcok;
struct os_mbuf *rxpdu;
struct ble_mbuf_hdr *ble_hdr;
- /* 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();
- }
-
- /* We get this if we have started to receive a frame */
- if ((irq_en & RADIO_INTENCLR_ADDRESS_Msk) && NRF_RADIO->EVENTS_ADDRESS) {
- /* Clear events and clear interrupt */
- NRF_RADIO->EVENTS_ADDRESS = 0;
- NRF_RADIO->INTENCLR = RADIO_INTENCLR_ADDRESS_Msk;
+ /* Clear events and clear interrupt */
+ NRF_RADIO->EVENTS_END = 0;
+ NRF_RADIO->INTENCLR = RADIO_INTENCLR_END_Msk;
- assert(g_ble_phy_data.rxpdu != NULL);
+ /* Disable automatic RXEN */
+ NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
- /* Wait to get 1st byte of frame */
- while (1) {
- state = NRF_RADIO->STATE;
- if (NRF_RADIO->EVENTS_BCMATCH != 0) {
- break;
+ /* Set RSSI and CRC status flag in header */
+ ble_hdr = BLE_MBUF_HDR_PTR(g_ble_phy_data.rxpdu);
+ assert(NRF_RADIO->EVENTS_RSSIEND != 0);
+ ble_hdr->rxinfo.rssi = -1 * NRF_RADIO->RSSISAMPLE;
+#ifdef BLE_LL_CFG_FEAT_LE_ENCRYPTION
+ dptr = g_ble_phy_data.rxpdu->om_data;
+#endif
+ /* Count PHY crc errors and valid packets */
+ crcok = (uint8_t)NRF_RADIO->CRCSTATUS;
+ if (!crcok) {
+ STATS_INC(ble_phy_stats, rx_crc_err);
+ } else {
+ STATS_INC(ble_phy_stats, rx_valid);
+ ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK;
+#ifdef BLE_LL_CFG_FEAT_LE_ENCRYPTION
+ if (g_ble_phy_data.phy_encrypted) {
+ /* Only set MIC failure flag if frame is not zero length */
+ if ((dptr[1] != 0) && (NRF_CCM->MICSTATUS == 0)) {
+ ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_MIC_FAILURE;
}
/*
- * If state is disabled, we should have the BCMATCH. If not,
- * something is wrong!
+ * XXX: not sure how to deal with this. This should not
+ * be a MIC failure but we should not hand it up. I guess
+ * this is just some form of rx error and that is how we
+ * handle it? For now, just set CRC error flags
*/
- if (state == RADIO_STATE_STATE_Disabled) {
- NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
- NRF_RADIO->SHORTS = 0;
- goto phy_isr_exit;
+ if (NRF_CCM->EVENTS_ERROR) {
+ STATS_INC(ble_phy_stats, rx_hw_err);
+ ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK;
}
- }
- /* Initialize flags, channel and state in ble header at rx start */
- ble_hdr = BLE_MBUF_HDR_PTR(g_ble_phy_data.rxpdu);
- ble_hdr->rxinfo.flags = ble_ll_state_get();
- ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan;
- ble_hdr->rxinfo.handle = 0;
-
- /* Call Link Layer receive start function */
- rc = ble_ll_rx_start(g_ble_phy_data.rxpdu, g_ble_phy_data.phy_chan);
- if (rc >= 0) {
- /* Set rx started flag and enable rx end ISR */
- g_ble_phy_data.phy_rx_started = 1;
- NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk;
- } else {
- /* Disable PHY */
- ble_phy_disable();
- irq_en = 0;
- STATS_INC(ble_phy_stats, rx_aborts);
+ /*
+ * XXX: This is a total hack work-around for now but I dont
+ * know what else to do. If ENDCRYPT is not set and we are
+ * encrypted we need to not trust this frame and drop it.
+ */
+ if (NRF_CCM->EVENTS_ENDCRYPT == 0) {
+ STATS_INC(ble_phy_stats, rx_hw_err);
+ ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK;
+ }
}
-
- /* Count rx starts */
- STATS_INC(ble_phy_stats, rx_starts);
+#endif
}
- /* Receive packet end (we dont enable this for transmit) */
- if ((irq_en & RADIO_INTENCLR_END_Msk) && NRF_RADIO->EVENTS_END) {
- /* Clear events and clear interrupt */
- NRF_RADIO->EVENTS_END = 0;
- NRF_RADIO->INTENCLR = RADIO_INTENCLR_END_Msk;
-
- /* Set RSSI and CRC status flag in header */
- ble_hdr = BLE_MBUF_HDR_PTR(g_ble_phy_data.rxpdu);
- assert(NRF_RADIO->EVENTS_RSSIEND != 0);
- ble_hdr->rxinfo.rssi = -1 * NRF_RADIO->RSSISAMPLE;
- ble_hdr->end_cputime = NRF_TIMER0->CC[2];
-#ifdef BLE_LL_CFG_FEAT_LE_ENCRYPTION
- dptr = g_ble_phy_data.rxpdu->om_data;
-#endif
- /* Count PHY crc errors and valid packets */
- crcok = (uint8_t)NRF_RADIO->CRCSTATUS;
- if (!crcok) {
- STATS_INC(ble_phy_stats, rx_crc_err);
- } else {
- STATS_INC(ble_phy_stats, rx_valid);
- ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CRC_OK;
+ /* Call Link Layer receive payload function */
+ rxpdu = g_ble_phy_data.rxpdu;
+ g_ble_phy_data.rxpdu = NULL;
+
#ifdef BLE_LL_CFG_FEAT_LE_ENCRYPTION
- if (g_ble_phy_data.phy_encrypted) {
- /* Only set MIC failure flag if frame is not zero length */
- if ((dptr[1] != 0) && (NRF_CCM->MICSTATUS == 0)) {
- ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_MIC_FAILURE;
- }
-
- /*
- * XXX: not sure how to deal with this. This should not
- * be a MIC failure but we should not hand it up. I guess
- * this is just some form of rx error and that is how we
- * handle it? For now, just set CRC error flags
- */
- if (NRF_CCM->EVENTS_ERROR) {
- STATS_INC(ble_phy_stats, rx_hw_err);
- ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK;
- }
-
- /*
- * XXX: This is a total hack work-around for now but I dont
- * know what else to do. If ENDCRYPT is not set and we are
- * encrypted we need to not trust this frame and drop it.
- */
- if (NRF_CCM->EVENTS_ENDCRYPT == 0) {
- STATS_INC(ble_phy_stats, rx_hw_err);
- ble_hdr->rxinfo.flags &= ~BLE_MBUF_HDR_F_CRC_OK;
- }
- }
+ if (g_ble_phy_data.phy_encrypted) {
+ /*
+ * XXX: This is a horrible ugly hack to deal with the RAM S1 byte.
+ * This should get fixed as we should not be handing up the header
+ * and length as part of the pdu.
+ */
+ dptr[2] = dptr[1];
+ dptr[1] = dptr[0];
+ rxpdu->om_data += 1;
+ }
#endif
- }
+ rc = ble_ll_rx_end(rxpdu, ble_hdr);
+ if (rc < 0) {
+ ble_phy_disable();
+ }
+}
- /* Call Link Layer receive payload function */
- rxpdu = g_ble_phy_data.rxpdu;
- g_ble_phy_data.rxpdu = NULL;
+static void
+ble_phy_rx_start_isr(void)
+{
+ int rc;
+ uint32_t state;
+ struct ble_mbuf_hdr *ble_hdr;
-#ifdef BLE_LL_CFG_FEAT_LE_ENCRYPTION
- if (g_ble_phy_data.phy_encrypted) {
- /*
- * XXX: This is a horrible ugly hack to deal with the RAM S1 byte.
- * This should get fixed as we should not be handing up the header
- * and length as part of the pdu.
- */
- dptr[2] = dptr[1];
- dptr[1] = dptr[0];
- rxpdu->om_data += 1;
+ /* Clear events and clear interrupt */
+ NRF_RADIO->EVENTS_ADDRESS = 0;
+ NRF_RADIO->INTENCLR = RADIO_INTENCLR_ADDRESS_Msk;
+
+ assert(g_ble_phy_data.rxpdu != NULL);
+
+ /* Wait to get 1st byte of frame */
+ while (1) {
+ state = NRF_RADIO->STATE;
+ if (NRF_RADIO->EVENTS_BCMATCH != 0) {
+ break;
}
-#endif
- rc = ble_ll_rx_end(rxpdu, ble_hdr);
- if (rc < 0) {
- ble_phy_disable();
+
+ /*
+ * If state is disabled, we should have the BCMATCH. If not,
+ * something is wrong!
+ */
+ if (state == RADIO_STATE_STATE_Disabled) {
+ NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
+ NRF_RADIO->SHORTS = 0;
+ return;
}
}
-phy_isr_exit:
+ /* Initialize flags, channel and state in ble header at rx start */
+ ble_hdr = BLE_MBUF_HDR_PTR(g_ble_phy_data.rxpdu);
+ 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] -
+ BLE_TX_LEN_USECS_M(NRF_RX_START_OFFSET);
+
+ /* Call Link Layer receive start function */
+ rc = ble_ll_rx_start(g_ble_phy_data.rxpdu, g_ble_phy_data.phy_chan);
+ if (rc >= 0) {
+ /* Set rx started flag and enable rx end ISR */
+ g_ble_phy_data.phy_rx_started = 1;
+ NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk;
+ } else {
+ /* Disable PHY */
+ ble_phy_disable();
+ STATS_INC(ble_phy_stats, rx_aborts);
+ }
+
+ /* Count rx starts */
+ STATS_INC(ble_phy_stats, rx_starts);
+}
+
+static void
+ble_phy_isr(void)
+{
+ uint32_t irq_en;
+
+ /* 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();
+ }
+
+ /* We get this if we have started to receive a frame */
+ if ((irq_en & RADIO_INTENCLR_ADDRESS_Msk) && NRF_RADIO->EVENTS_ADDRESS) {
+ ble_phy_rx_start_isr();
+ }
+
+ /* 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();
+ }
+
/* Ensures IRQ is cleared */
- state = NRF_RADIO->SHORTS;
+ irq_en = NRF_RADIO->SHORTS;
/* Count # of interrupts */
STATS_INC(ble_phy_stats, phy_isrs);
@@ -546,11 +573,8 @@ ble_phy_init(void)
/* Configure IFS */
NRF_RADIO->TIFS = BLE_LL_IFS;
- /*
- * Enable the pre-programmed PPI to capture the time when a receive
- * or transmit ends
- */
- NRF_PPI->CHENSET = PPI_CHEN_CH27_Msk;
+ /* Captures tx/rx start in timer0 capture 1 */
+ NRF_PPI->CHENSET = PPI_CHEN_CH26_Msk;
#ifdef BLE_LL_CFG_FEAT_LE_ENCRYPTION
NRF_CCM->INTENCLR = 0xffffffff;
@@ -611,8 +635,12 @@ ble_phy_rx(void)
/* Setup for rx */
ble_phy_rx_xcvr_setup();
- /* Start the receive task in the radio */
- NRF_RADIO->TASKS_RXEN = 1;
+ /* Start the receive task in the radio if not automatically going to rx */
+ if ((NRF_PPI->CHEN & PPI_CHEN_CH21_Msk) == 0) {
+ NRF_RADIO->TASKS_RXEN = 1;
+ }
+
+ ble_ll_log(BLE_LL_LOG_ID_PHY_RX, g_ble_phy_data.phy_encrypted, 0, 0);
return 0;
}
@@ -674,11 +702,76 @@ ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg)
g_ble_phy_data.txend_arg = arg;
}
+/**
+ * Called to set the start time of a transmission.
+ *
+ * This function is called to set the start time when we are not going from
+ * rx to tx automatically.
+ *
+ * NOTE: care must be taken when calling this function. The channel should
+ * already be set.
+ *
+ * @param cputime
+ *
+ * @return int
+ */
+int
+ble_phy_tx_set_start_time(uint32_t cputime)
+{
+ int rc;
+
+ NRF_TIMER0->CC[0] = cputime;
+ NRF_PPI->CHENSET = PPI_CHEN_CH20_Msk;
+ NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk;
+ if ((int32_t)(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;
+}
+
+/**
+ * Called to set the start time of a reception
+ *
+ * This function acts a bit differently than transmit. If we are late getting
+ * here we will still attempt to receive.
+ *
+ * NOTE: care must be taken when calling this function. The channel should
+ * already be set.
+ *
+ * @param cputime
+ *
+ * @return int
+ */
int
-ble_phy_tx(struct os_mbuf *txpdu, uint8_t beg_trans, uint8_t end_trans)
+ble_phy_rx_set_start_time(uint32_t cputime)
+{
+ int rc;
+
+ NRF_TIMER0->CC[0] = cputime;
+ NRF_PPI->CHENCLR = PPI_CHEN_CH20_Msk;
+ NRF_PPI->CHENSET = PPI_CHEN_CH21_Msk;
+ if ((int32_t)(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;
+ } else {
+ rc = 0;
+ }
+ return rc;
+}
+
+
+int
+ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans)
{
int rc;
uint8_t *dptr;
+ uint8_t payload_len;
uint32_t state;
uint32_t shortcuts;
struct ble_mbuf_hdr *ble_hdr;
@@ -686,37 +779,24 @@ ble_phy_tx(struct os_mbuf *txpdu, uint8_t beg_trans, uint8_t end_trans)
/* Better have a pdu! */
assert(txpdu != NULL);
- /* If radio is not disabled, */
+ /*
+ * This check is to make sure that the radio is not in a state where
+ * it is moving to disabled state. If so, let it get there.
+ */
nrf_wait_disabled();
- if (beg_trans == BLE_PHY_TRANSITION_RX_TX) {
- if ((NRF_RADIO->SHORTS & RADIO_SHORTS_DISABLED_TXEN_Msk) == 0) {
- assert(0);
- }
- /* Radio better be in TXRU state or we are in bad shape */
- state = RADIO_STATE_STATE_TxRu;
- } else {
- /* Radio should be in disabled state */
- state = RADIO_STATE_STATE_Disabled;
- }
-
- if (NRF_RADIO->STATE != state) {
- ble_phy_disable();
- STATS_INC(ble_phy_stats, radio_state_errs);
- return BLE_PHY_ERR_RADIO_STATE;
- }
+ ble_hdr = BLE_MBUF_HDR_PTR(txpdu);
+ payload_len = ble_hdr->txinfo.pyld_len;
#ifdef BLE_LL_CFG_FEAT_LE_ENCRYPTION
if (g_ble_phy_data.phy_encrypted) {
/* RAM representation has S0, LENGTH and S1 fields. (3 bytes) */
- ble_hdr = BLE_MBUF_HDR_PTR(txpdu);
dptr = (uint8_t *)&g_ble_phy_enc_buf[0];
dptr[0] = ble_hdr->txinfo.hdr_byte;
- dptr[1] = ble_hdr->txinfo.pyld_len;
+ dptr[1] = payload_len;
dptr[2] = 0;
dptr += 3;
- NRF_RADIO->PACKETPTR = (uint32_t)&g_ble_phy_txrx_buf[0];
NRF_CCM->SHORTS = 1;
NRF_CCM->INPTR = (uint32_t)&g_ble_phy_enc_buf[0];
NRF_CCM->OUTPTR = (uint32_t)&g_ble_phy_txrx_buf[0];
@@ -728,24 +808,19 @@ ble_phy_tx(struct os_mbuf *txpdu, uint8_t beg_trans, uint8_t end_trans)
NRF_PPI->CHENSET = PPI_CHEN_CH24_Msk;
} else {
/* RAM representation has S0 and LENGTH fields (2 bytes) */
- ble_hdr = BLE_MBUF_HDR_PTR(txpdu);
dptr = (uint8_t *)&g_ble_phy_txrx_buf[0];
dptr[0] = ble_hdr->txinfo.hdr_byte;
- dptr[1] = ble_hdr->txinfo.pyld_len;
+ dptr[1] = payload_len;
dptr += 2;
-
- NRF_RADIO->PACKETPTR = (uint32_t)&g_ble_phy_txrx_buf[0];
}
#else
/* RAM representation has S0 and LENGTH fields (2 bytes) */
- ble_hdr = BLE_MBUF_HDR_PTR(txpdu);
dptr = (uint8_t *)&g_ble_phy_txrx_buf[0];
dptr[0] = ble_hdr->txinfo.hdr_byte;
- dptr[1] = ble_hdr->txinfo.pyld_len;
+ dptr[1] = payload_len;
dptr += 2;
-
- NRF_RADIO->PACKETPTR = (uint32_t)&g_ble_phy_txrx_buf[0];
#endif
+ NRF_RADIO->PACKETPTR = (uint32_t)&g_ble_phy_txrx_buf[0];
/* Clear the ready, end and disabled events */
NRF_RADIO->EVENTS_READY = 0;
@@ -763,36 +838,26 @@ ble_phy_tx(struct os_mbuf *txpdu, uint8_t beg_trans, uint8_t end_trans)
NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk;
NRF_RADIO->SHORTS = shortcuts;
- /* Trigger transmit if our state was disabled */
- if (state == RADIO_STATE_STATE_Disabled) {
- NRF_RADIO->TASKS_TXEN = 1;
- }
+ /* Set transmitted payload length */
+ g_ble_phy_data.phy_tx_pyld_len = payload_len;
/* Set the PHY transition */
g_ble_phy_data.phy_transition = end_trans;
- /* Read back radio state. If in TXRU, we are fine */
+ /* If we already started transmitting, abort it! */
state = NRF_RADIO->STATE;
- if (state == RADIO_STATE_STATE_TxRu) {
+ if (state != RADIO_STATE_STATE_Tx) {
/* Copy data from mbuf into transmit buffer */
- os_mbuf_copydata(txpdu, ble_hdr->txinfo.offset,
- ble_hdr->txinfo.pyld_len, dptr);
+ os_mbuf_copydata(txpdu, ble_hdr->txinfo.offset, payload_len, dptr);
/* Set phy state to transmitting and count packet statistics */
g_ble_phy_data.phy_state = BLE_PHY_STATE_TX;
STATS_INC(ble_phy_stats, tx_good);
- STATS_INCN(ble_phy_stats, tx_bytes,
- ble_hdr->txinfo.pyld_len + BLE_LL_PDU_HDR_LEN);
+ STATS_INCN(ble_phy_stats, tx_bytes, payload_len + BLE_LL_PDU_HDR_LEN);
rc = BLE_ERR_SUCCESS;
} else {
- if (state == RADIO_STATE_STATE_Tx) {
- STATS_INC(ble_phy_stats, tx_late);
- } else {
- STATS_INC(ble_phy_stats, tx_fail);
- }
-
- /* Frame failed to transmit */
ble_phy_disable();
+ STATS_INC(ble_phy_stats, tx_late);
rc = BLE_PHY_ERR_RADIO_STATE;
}
@@ -932,6 +997,7 @@ ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit)
* -> 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.
@@ -944,6 +1010,7 @@ ble_phy_disable(void)
NRF_RADIO->INTENCLR = NRF_RADIO_IRQ_MASK_ALL;
NRF_RADIO->SHORTS = 0;
NRF_RADIO->TASKS_DISABLE = 1;
+ NRF_PPI->CHENCLR = PPI_CHEN_CH21_Msk | PPI_CHEN_CH20_Msk;
NVIC_ClearPendingIRQ(RADIO_IRQn);
g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
}
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8ddc20ee/net/nimble/drivers/nrf52/include/ble/xcvr.h
----------------------------------------------------------------------
diff --git a/net/nimble/drivers/nrf52/include/ble/xcvr.h b/net/nimble/drivers/nrf52/include/ble/xcvr.h
new file mode 100644
index 0000000..f3e60fa
--- /dev/null
+++ b/net/nimble/drivers/nrf52/include/ble/xcvr.h
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_BLE_XCVR_
+#define H_BLE_XCVR_
+
+/* Transceiver specific defintions */
+#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 \
+ (XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
+
+#endif /* H_BLE_XCVR_ */