Bluetooth: Controller: ctrl pdu processing based on available CPU time
On CPUs like nRF51 which run at 16MHz, certain BLE control procedure PDU processing take more CPU time than permitted inside tIFS (150us). Current implementation of Data Length Update procedure does not span over multiple connection interval (unlike Encryption Setup, which is another control procedure processing that would consume more CPU time) hence taking more CPU time inside tIFS on nRF51. During the radio ISR, the active clock and packet timer are active and it is used to profile the CPU time taken which is used to decide on whether there is sufficient time in the current radio event to process the control packet. This commit also fixes a potential bug that would cause disconnection due to MIC failure on encrypted connections that performed Data Length Update. Controller used to NACK the request/response PDU if it was not in a state to resize the receive buffers but did not reset the CCM counter. This is now fixed by the change done to NACK control PDU based on available CPU time in radio ISR. Change-id: Id58322ad76a0dbc284738cdd9a7c0437c9e8c423 Signed-off-by: Vinayak Chettimada <vinayak.kariappa.chettimada@nordicsemi.no>
This commit is contained in:
parent
c776791ed0
commit
6de7a808af
3 changed files with 52 additions and 15 deletions
|
@ -421,6 +421,16 @@ uint32_t radio_tmr_end_get(void)
|
|||
return NRF_TIMER0->CC[2];
|
||||
}
|
||||
|
||||
void radio_tmr_sample(void)
|
||||
{
|
||||
NRF_TIMER0->TASKS_CAPTURE[3] = 1;
|
||||
}
|
||||
|
||||
uint32_t radio_tmr_sample_get(void)
|
||||
{
|
||||
return NRF_TIMER0->CC[3];
|
||||
}
|
||||
|
||||
static uint8_t ALIGNED(4) _ccm_scratch[(RADIO_PDU_LEN_MAX - 4) + 16];
|
||||
|
||||
void *radio_ccm_rx_pkt_set(struct ccm *ccm, void *pkt)
|
||||
|
|
|
@ -94,6 +94,8 @@ void radio_tmr_aa_capture(void);
|
|||
uint32_t radio_tmr_aa_get(void);
|
||||
void radio_tmr_end_capture(void);
|
||||
uint32_t radio_tmr_end_get(void);
|
||||
void radio_tmr_sample(void);
|
||||
uint32_t radio_tmr_sample_get(void);
|
||||
|
||||
void *radio_ccm_rx_pkt_set(struct ccm *ccm, void *pkt);
|
||||
void *radio_ccm_tx_pkt_set(struct ccm *ccm, void *pkt);
|
||||
|
|
|
@ -1219,12 +1219,12 @@ isr_rx_conn_pkt_ctrl_rej(struct radio_pdu_node_rx *radio_pdu_node_rx,
|
|||
|
||||
}
|
||||
|
||||
static inline void isr_rx_conn_pkt_ctrl_dle(struct pdu_data *pdu_data_rx,
|
||||
static inline uint8_t isr_rx_conn_pkt_ctrl_dle(struct pdu_data *pdu_data_rx,
|
||||
uint8_t *rx_enqueue)
|
||||
{
|
||||
uint16_t eff_rx_octets;
|
||||
uint16_t eff_tx_octets;
|
||||
uint8_t no_resp = 0;
|
||||
uint8_t nack = 0;
|
||||
|
||||
eff_rx_octets = _radio.conn_curr->max_rx_octets;
|
||||
eff_tx_octets = _radio.conn_curr->max_tx_octets;
|
||||
|
@ -1300,10 +1300,7 @@ static inline void isr_rx_conn_pkt_ctrl_dle(struct pdu_data *pdu_data_rx,
|
|||
*/
|
||||
_radio.state = STATE_CLOSE;
|
||||
} else {
|
||||
/* nack ctrl packet */
|
||||
_radio.conn_curr->nesn--;
|
||||
|
||||
no_resp = 1;
|
||||
nack = 1;
|
||||
}
|
||||
} else {
|
||||
/* resume data packet tx */
|
||||
|
@ -1333,16 +1330,20 @@ static inline void isr_rx_conn_pkt_ctrl_dle(struct pdu_data *pdu_data_rx,
|
|||
}
|
||||
|
||||
if ((PDU_DATA_LLCTRL_TYPE_LENGTH_REQ ==
|
||||
pdu_data_rx->payload.llctrl.opcode) && !no_resp) {
|
||||
pdu_data_rx->payload.llctrl.opcode) && !nack) {
|
||||
length_resp_send(_radio.conn_curr, eff_rx_octets,
|
||||
eff_tx_octets);
|
||||
}
|
||||
|
||||
return nack;
|
||||
}
|
||||
|
||||
static inline void
|
||||
static inline uint8_t
|
||||
isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *radio_pdu_node_rx,
|
||||
struct pdu_data *pdu_data_rx, uint8_t *rx_enqueue)
|
||||
{
|
||||
uint8_t nack = 0;
|
||||
|
||||
switch (pdu_data_rx->payload.llctrl.opcode) {
|
||||
case PDU_DATA_LLCTRL_TYPE_CONN_UPDATE_REQ:
|
||||
if (conn_update(_radio.conn_curr, pdu_data_rx) == 0) {
|
||||
|
@ -1733,7 +1734,7 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *radio_pdu_node_rx,
|
|||
|
||||
case PDU_DATA_LLCTRL_TYPE_LENGTH_RSP:
|
||||
case PDU_DATA_LLCTRL_TYPE_LENGTH_REQ:
|
||||
isr_rx_conn_pkt_ctrl_dle(pdu_data_rx, rx_enqueue);
|
||||
nack = isr_rx_conn_pkt_ctrl_dle(pdu_data_rx, rx_enqueue);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -1742,12 +1743,14 @@ isr_rx_conn_pkt_ctrl(struct radio_pdu_node_rx *radio_pdu_node_rx,
|
|||
break;
|
||||
}
|
||||
|
||||
return nack;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
isr_rx_conn_pkt(struct radio_pdu_node_rx *radio_pdu_node_rx,
|
||||
struct pdu_data *pdu_data_rx)
|
||||
{
|
||||
uint8_t nack = 0;
|
||||
uint8_t terminate = 0;
|
||||
struct pdu_data *pdu_data_tx;
|
||||
|
||||
|
@ -1821,13 +1824,12 @@ isr_rx_conn_pkt(struct radio_pdu_node_rx *radio_pdu_node_rx,
|
|||
((_radio.fc_req != 0) &&
|
||||
(_radio.fc_handle[_radio.fc_req - 1] ==
|
||||
_radio.conn_curr->handle)))))) {
|
||||
_radio.conn_curr->nesn++;
|
||||
uint8_t ccm_rx_increment = 0;
|
||||
|
||||
if (pdu_data_rx->len != 0) {
|
||||
uint8_t rx_enqueue = 0;
|
||||
|
||||
/* If required wait for CCM to finish and then
|
||||
* increment counter
|
||||
/* If required, wait for CCM to finish
|
||||
*/
|
||||
if (_radio.conn_curr->enc_rx) {
|
||||
uint32_t done;
|
||||
|
@ -1835,7 +1837,7 @@ isr_rx_conn_pkt(struct radio_pdu_node_rx *radio_pdu_node_rx,
|
|||
done = radio_ccm_is_done();
|
||||
LL_ASSERT(done);
|
||||
|
||||
_radio.conn_curr->ccm_rx.counter++;
|
||||
ccm_rx_increment = 1;
|
||||
}
|
||||
|
||||
/* MIC Failure Check or data rx during pause */
|
||||
|
@ -1867,8 +1869,23 @@ isr_rx_conn_pkt(struct radio_pdu_node_rx *radio_pdu_node_rx,
|
|||
break;
|
||||
|
||||
case PDU_DATA_LLID_CTRL:
|
||||
isr_rx_conn_pkt_ctrl(radio_pdu_node_rx,
|
||||
pdu_data_rx, &rx_enqueue);
|
||||
/* Handling control procedure takes more CPU
|
||||
* time hence check how much CPU time we have
|
||||
* used up inside tIFS (150us) and decide to
|
||||
* NACK rx-ed packet if consumed more than half
|
||||
* the tIFS value. Control Procedure will be
|
||||
* handled in the next re-transmission of the
|
||||
* packet by peer.
|
||||
*/
|
||||
radio_tmr_sample();
|
||||
if ((radio_tmr_sample_get() -
|
||||
radio_tmr_end_get()) < 75) {
|
||||
nack = isr_rx_conn_pkt_ctrl(
|
||||
radio_pdu_node_rx,
|
||||
pdu_data_rx, &rx_enqueue);
|
||||
} else {
|
||||
nack = 1;
|
||||
}
|
||||
break;
|
||||
case PDU_DATA_LLID_RESV:
|
||||
default:
|
||||
|
@ -1897,6 +1914,14 @@ isr_rx_conn_pkt(struct radio_pdu_node_rx *radio_pdu_node_rx,
|
|||
_radio.conn_curr->apto_reload;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nack) {
|
||||
_radio.conn_curr->nesn++;
|
||||
|
||||
if (ccm_rx_increment) {
|
||||
_radio.conn_curr->ccm_rx.counter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue