Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | /*
* Copyright (c) 2018-2019 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <toolchain.h>
#include <zephyr/types.h>
#include "hal/ccm.h"
#include "hal/radio.h"
#include "util/memq.h"
#include "pdu.h"
#include "lll.h"
static u8_t latency_min = (u8_t) -1;
static u8_t latency_max;
static u8_t latency_prev;
static u8_t cputime_min = (u8_t) -1;
static u8_t cputime_max;
static u8_t cputime_prev;
static u32_t timestamp_latency;
void lll_prof_latency_capture(void)
{
/* sample the packet timer, use it to calculate ISR latency
* and generate the profiling event at the end of the ISR.
*/
radio_tmr_sample();
}
#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
static u32_t timestamp_radio_end;
u32_t lll_prof_radio_end_backup(void)
{
/* PA enable is overwriting packet end used in ISR profiling, hence
* back it up for later use.
*/
timestamp_radio_end = radio_tmr_end_get();
return timestamp_radio_end;
}
#endif /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
void lll_prof_cputime_capture(void)
{
/* get the ISR latency sample */
timestamp_latency = radio_tmr_sample_get();
/* sample the packet timer again, use it to calculate ISR execution time
* and use it in profiling event
*/
radio_tmr_sample();
}
void lll_prof_send(void)
{
u8_t latency, cputime, prev;
u8_t chg = 0U;
/* calculate the elapsed time in us since on-air radio packet end
* to ISR entry
*/
#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
latency = timestamp_latency - timestamp_radio_end;
#else /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
latency = timestamp_latency - radio_tmr_end_get();
#endif /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
/* check changes in min, avg and max of latency */
if (latency > latency_max) {
latency_max = latency;
chg = 1U;
}
if (latency < latency_min) {
latency_min = latency;
chg = 1U;
}
/* check for +/- 1us change */
prev = ((u16_t)latency_prev + latency) >> 1;
if (prev != latency_prev) {
latency_prev = latency;
chg = 1U;
}
/* calculate the elapsed time in us since ISR entry */
cputime = radio_tmr_sample_get() - timestamp_latency;
/* check changes in min, avg and max */
if (cputime > cputime_max) {
cputime_max = cputime;
chg = 1U;
}
if (cputime < cputime_min) {
cputime_min = cputime;
chg = 1U;
}
/* check for +/- 1us change */
prev = ((u16_t)cputime_prev + cputime) >> 1;
if (prev != cputime_prev) {
cputime_prev = cputime;
chg = 1U;
}
/* generate event if any change */
if (chg) {
struct node_rx_pdu *rx;
/* NOTE: enqueue only if rx buffer available, else ignore */
rx = ull_pdu_rx_alloc_peek(3);
if (rx) {
struct pdu_data *pdu;
struct profile *p;
ull_pdu_rx_alloc();
rx->hdr.type = NODE_RX_TYPE_PROFILE;
rx->hdr.handle = 0xFFFF;
pdu = (void *)rx->pdu;
p = &pdu->profile;
p->lcur = latency;
p->lmin = latency_min;
p->lmax = latency_max;
p->cur = cputime;
p->min = cputime_min;
p->max = cputime_max;
ull_rx_put(rx->hdr.link, rx);
ull_rx_sched();
}
}
}
|