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_ */