Bluetooth: controller: Add Coded PHY packet tx time restrictions

Add implementation to support Coded PHY update procedure
with packet transmit time restrictions.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2017-10-14 23:29:34 +02:00 committed by Carles Cufí
commit 52bc2b6cd1
2 changed files with 88 additions and 44 deletions

View file

@ -42,11 +42,15 @@
#define RADIO_TIFS 150
#define RADIO_CONN_EVENTS(x, y) ((u16_t)(((x) + (y) - 1) / (y)))
/* Convert payload length to tx/rx time
* On 1M PHY, add 14 bytes for preamble (1), access address (4),
* header (2), MIC (4), and CRC (3). Convert to bits (1 Msps).
*/
#define RADIO_PKT_TIME(octets) (((octets) + 14) << 3)
#if defined(CONFIG_BT_CTLR_PHY_CODED)
#define RADIO_PKT_TIME(octets, phy) \
(((phy) & BIT(2)) ? (80 + 256 + 16 + 24 + ((((2 + (octets) + 4) * 8) + \
24 + 3) * 8)) : \
(((octets) + 14) * 8 / BIT(((phy) & 0x03) >> 1)))
#else /* !CONFIG_BT_CTLR_PHY_CODED */
#define RADIO_PKT_TIME(octets, phy) \
(((octets) + 14) * 8 / BIT(((phy) & 0x03) >> 1))
#endif /* !CONFIG_BT_CTLR_PHY_CODED */
#define RADIO_TICKER_JITTER_US 16
#define RADIO_TICKER_START_PART_US 300
@ -549,7 +553,8 @@ static void common_init(void)
#if defined(CONFIG_BT_CTLR_DATA_LENGTH)
/* Initialize the DLE defaults */
_radio.default_tx_octets = RADIO_LL_LENGTH_OCTETS_RX_MIN;
_radio.default_tx_time = RADIO_LL_LENGTH_TIME_RX_MIN;
_radio.default_tx_time = RADIO_PKT_TIME(RADIO_LL_LENGTH_OCTETS_RX_MIN,
0);
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
#if defined(CONFIG_BT_CTLR_PHY)
@ -2019,8 +2024,8 @@ isr_rx_conn_pkt_ctrl_rej_dle(struct radio_pdu_node_rx *radio_pdu_node_rx,
lr->max_rx_octets = conn->max_rx_octets;
lr->max_tx_octets = conn->max_tx_octets;
#if !defined(CONFIG_BT_CTLR_PHY)
lr->max_rx_time = RADIO_PKT_TIME(conn->max_rx_octets);
lr->max_tx_time = RADIO_PKT_TIME(conn->max_tx_octets);
lr->max_rx_time = RADIO_PKT_TIME(conn->max_rx_octets, 0);
lr->max_tx_time = RADIO_PKT_TIME(conn->max_tx_octets, 0);
#else /* CONFIG_BT_CTLR_PHY */
lr->max_rx_time = conn->max_rx_time;
lr->max_tx_time = conn->max_tx_time;
@ -2217,7 +2222,8 @@ static inline u8_t isr_rx_conn_pkt_ctrl_dle(struct pdu_data *pdu_data_rx,
/* use the minimal of our default_tx_time and
* peer max_rx_time
*/
if (lr->max_rx_time >= RADIO_LL_LENGTH_TIME_RX_MIN) {
if (lr->max_rx_time >=
RADIO_PKT_TIME(RADIO_LL_LENGTH_OCTETS_RX_MIN, 0)) {
eff_tx_time = min(lr->max_rx_time,
_radio.conn_curr->default_tx_time);
}
@ -2225,9 +2231,11 @@ static inline u8_t isr_rx_conn_pkt_ctrl_dle(struct pdu_data *pdu_data_rx,
/* use the minimal of our max supported and
* peer max_tx_time
*/
if (lr->max_tx_time >= RADIO_LL_LENGTH_TIME_RX_MIN) {
if (lr->max_tx_time >=
RADIO_PKT_TIME(RADIO_LL_LENGTH_OCTETS_RX_MIN, 0)) {
eff_rx_time = min(lr->max_tx_time,
RADIO_LL_LENGTH_TIME_RX_MAX);
RADIO_PKT_TIME(RADIO_LL_LENGTH_OCTETS_RX_MAX,
BIT(2)));
}
#endif /* CONFIG_BT_CTLR_PHY */
@ -2299,8 +2307,8 @@ static inline u8_t isr_rx_conn_pkt_ctrl_dle(struct pdu_data *pdu_data_rx,
lr->max_tx_octets = eff_tx_octets;
#if !defined(CONFIG_BT_CTLR_PHY)
lr->max_rx_time = RADIO_PKT_TIME(eff_rx_octets);
lr->max_tx_time = RADIO_PKT_TIME(eff_tx_octets);
lr->max_rx_time = RADIO_PKT_TIME(eff_rx_octets, 0);
lr->max_tx_time = RADIO_PKT_TIME(eff_tx_octets, 0);
#else /* CONFIG_BT_CTLR_PHY */
lr->max_rx_time = eff_rx_time;
lr->max_tx_time = eff_tx_time;
@ -2997,24 +3005,37 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *radio_pdu_node_rx,
_radio.conn_curr->llcp_phy.rx &= p->tx_phys;
}
} else {
phy_rsp_send(_radio.conn_curr);
struct pdu_data_llctrl *c =
&pdu_data_rx->payload.llctrl;
struct pdu_data_llctrl_phy_req_rsp *p =
&c->ctrldata.phy_req;
_radio.conn_curr->llcp_phy.state =
LLCP_PHY_STATE_RSP_WAIT;
/* Wait for peer master to complete the procedure */
if (_radio.conn_curr->llcp_phy.ack ==
_radio.conn_curr->llcp_phy.req) {
_radio.conn_curr->llcp_phy.ack--;
_radio.conn_curr->llcp_phy.state =
LLCP_PHY_STATE_RSP_WAIT;
_radio.conn_curr->llcp_phy.cmd = 0;
_radio.conn_curr->llcp_phy.tx =
_radio.conn_curr->phy_pref_tx;
_radio.conn_curr->llcp_phy.rx =
_radio.conn_curr->phy_pref_rx;
/* Start Procedure Timeout (TODO: this shall not
* replace terminate procedure).
*/
_radio.conn_curr->procedure_expire =
_radio.conn_curr->procedure_reload;
}
_radio.conn_curr->llcp_phy.tx &= p->rx_phys;
_radio.conn_curr->llcp_phy.rx &= p->tx_phys;
phy_rsp_send(_radio.conn_curr);
}
break;
@ -7304,9 +7325,10 @@ static inline void event_len_prep(struct connection *conn)
&pdu_ctrl_tx->payload.llctrl.ctrldata.length_req;
lr->max_rx_octets = RADIO_LL_LENGTH_OCTETS_RX_MAX;
lr->max_tx_octets = conn->default_tx_octets;
lr->max_rx_time = RADIO_PKT_TIME(RADIO_LL_LENGTH_OCTETS_RX_MAX);
lr->max_rx_time = RADIO_PKT_TIME(RADIO_LL_LENGTH_OCTETS_RX_MAX,
BIT(2));
#if !defined(CONFIG_BT_CTLR_PHY)
lr->max_tx_time = RADIO_PKT_TIME(conn->default_tx_octets);
lr->max_tx_time = RADIO_PKT_TIME(conn->default_tx_octets, 0);
#else /* CONFIG_BT_CTLR_PHY */
lr->max_tx_time = conn->default_tx_time;
#endif /* CONFIG_BT_CTLR_PHY */
@ -7462,8 +7484,8 @@ static inline void event_len_prep(struct connection *conn)
lr->max_rx_octets = conn->max_rx_octets;
lr->max_tx_octets = conn->max_tx_octets;
#if !defined(CONFIG_BT_CTLR_PHY)
lr->max_rx_time = RADIO_PKT_TIME(conn->max_rx_octets);
lr->max_tx_time = RADIO_PKT_TIME(conn->max_tx_octets);
lr->max_rx_time = RADIO_PKT_TIME(conn->max_rx_octets, 0);
lr->max_tx_time = RADIO_PKT_TIME(conn->max_tx_octets, 0);
#else /* CONFIG_BT_CTLR_PHY */
lr->max_rx_time = conn->max_rx_time;
lr->max_tx_time = conn->max_tx_time;
@ -8363,16 +8385,46 @@ static void prepare_pdu_data_tx(struct connection *conn,
switch (conn->phy_tx_time) {
default:
case BIT(0):
/* 1M PHY, 1us = 1 bit, hence divide by 8 */
max_tx_octets = conn->max_tx_time >> 3;
/* 1M PHY, 1us = 1 bit, hence divide by 8.
* Deduct 10 bytes for preamble (1), access address (4),
* header (2), and CRC (3).
*/
max_tx_octets = (conn->max_tx_time >> 3) - 10;
break;
case BIT(1):
/* 2M PHY, 1us = 2 bits, hence divide by 4.
* Substract the additional preamble octet (1).
* Deduct 11 bytes for preamble (2), access address (4),
* header (2), and CRC (3).
*/
max_tx_octets = (conn->max_tx_time >> 2) - 1;
max_tx_octets = (conn->max_tx_time >> 2) - 11;
break;
#if defined(CONFIG_BT_CTLR_PHY_CODED)
case BIT(2):
if (conn->phy_flags & 0x01) {
/* S8 Coded PHY, 8us = 1 bit, hence divide by
* 64.
* Subtract time for preamble (80), AA (256),
* CI (16), TERM1 (24), CRC (192) and
* TERM2 (24), total 592 us.
* Subtract 2 bytes for header.
*/
max_tx_octets = ((conn->max_tx_time - 592) >>
6) - 2;
} else {
/* S2 Coded PHY, 2us = 1 bit, hence divide by
* 16.
* Subtract time for preamble (80), AA (256),
* CI (16), TERM1 (24), CRC (48) and
* TERM2 (6), total 430 us.
* Subtract 2 bytes for header.
*/
max_tx_octets = ((conn->max_tx_time - 430) >>
4) - 2;
}
break;
#endif /* CONFIG_BT_CTLR_PHY_CODED */
}
if (conn->enc_tx) {
@ -8380,11 +8432,6 @@ static void prepare_pdu_data_tx(struct connection *conn,
max_tx_octets -= 4;
}
/* deduct 10 bytes for preamble (1), access address (4),
* header (2), and CRC (3).
*/
max_tx_octets -= 10;
if (max_tx_octets > conn->max_tx_octets) {
max_tx_octets = conn->max_tx_octets;
}
@ -9278,9 +9325,9 @@ static void length_resp_send(struct connection *conn, u16_t eff_rx_octets,
#if !defined(CONFIG_BT_CTLR_PHY)
pdu_ctrl_tx->payload.llctrl.ctrldata.length_rsp.max_rx_time =
RADIO_PKT_TIME(eff_rx_octets);
RADIO_PKT_TIME(eff_rx_octets, 0);
pdu_ctrl_tx->payload.llctrl.ctrldata.length_rsp.max_tx_time =
RADIO_PKT_TIME(eff_tx_octets);
RADIO_PKT_TIME(eff_tx_octets, 0);
#else /* CONFIG_BT_CTLR_PHY */
pdu_ctrl_tx->payload.llctrl.ctrldata.length_rsp.max_rx_time =
eff_rx_time;
@ -9671,8 +9718,10 @@ u32_t radio_adv_enable(u16_t interval, u8_t chan_map, u8_t filter_policy,
#if defined(CONFIG_BT_CTLR_PHY)
conn->default_tx_time = _radio.default_tx_time;
conn->max_tx_time = RADIO_LL_LENGTH_TIME_RX_MIN;
conn->max_rx_time = RADIO_LL_LENGTH_TIME_RX_MIN;
conn->max_tx_time =
RADIO_PKT_TIME(RADIO_LL_LENGTH_OCTETS_RX_MIN, 0);
conn->max_rx_time =
RADIO_PKT_TIME(RADIO_LL_LENGTH_OCTETS_RX_MIN, 0);
#endif /* CONFIG_BT_CTLR_PHY */
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
@ -10134,8 +10183,8 @@ u32_t radio_connect_enable(u8_t adv_addr_type, u8_t *adv_addr, u16_t interval,
#if defined(CONFIG_BT_CTLR_PHY)
conn->default_tx_time = _radio.default_tx_time;
conn->max_tx_time = RADIO_LL_LENGTH_TIME_RX_MIN;
conn->max_rx_time = RADIO_LL_LENGTH_TIME_RX_MIN;
conn->max_tx_time = RADIO_PKT_TIME(RADIO_LL_LENGTH_OCTETS_RX_MIN, 0);
conn->max_rx_time = RADIO_PKT_TIME(RADIO_LL_LENGTH_OCTETS_RX_MIN, 0);
#endif /* CONFIG_BT_CTLR_PHY */
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */
@ -10648,9 +10697,9 @@ void ll_length_max_get(u16_t *max_tx_octets, u16_t *max_tx_time,
u16_t *max_rx_octets, u16_t *max_rx_time)
{
*max_tx_octets = RADIO_LL_LENGTH_OCTETS_RX_MAX;
*max_tx_time = RADIO_LL_LENGTH_TIME_RX_MAX;
*max_tx_time = RADIO_PKT_TIME(RADIO_LL_LENGTH_OCTETS_RX_MAX, BIT(2));
*max_rx_octets = RADIO_LL_LENGTH_OCTETS_RX_MAX;
*max_rx_time = RADIO_LL_LENGTH_TIME_RX_MAX;
*max_rx_time = RADIO_PKT_TIME(RADIO_LL_LENGTH_OCTETS_RX_MAX, BIT(2));
}
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */

View file

@ -175,17 +175,12 @@
****************************************************************************/
/* Minimum LL Payload support (Dont change). */
#define RADIO_LL_LENGTH_OCTETS_RX_MIN 27
#define RADIO_LL_LENGTH_TIME_RX_MIN (((RADIO_LL_LENGTH_OCTETS_RX_MIN) \
+ 14) * 8 \
)
/* Maximum LL Payload support (27 to 251). */
#ifndef RADIO_LL_LENGTH_OCTETS_RX_MAX
#define RADIO_LL_LENGTH_OCTETS_RX_MAX 251
#endif
#define RADIO_LL_LENGTH_TIME_RX_MAX (((RADIO_LL_LENGTH_OCTETS_RX_MAX) \
+ 14) * 8 \
)
/* Implementation default L2CAP MTU */
#ifndef RADIO_L2CAP_MTU_MAX
#define RADIO_L2CAP_MTU_MAX (RADIO_LL_LENGTH_OCTETS_RX_MAX - 4)