/** * Count Link Layer statistics for received PDUs * * Context: Link layer task * * @param hdr * @param len */ static void ble_ll_count_rx_stats(struct ble_mbuf_hdr *hdr, uint16_t len, uint8_t pdu_type) { uint8_t crcok; uint8_t chan; crcok = BLE_MBUF_HDR_CRC_OK(hdr); chan = hdr->rxinfo.channel; if (crcok) { if (chan < BLE_PHY_NUM_DATA_CHANS) { STATS_INC(ble_ll_stats, rx_data_pdu_crc_ok); STATS_INCN(ble_ll_stats, rx_data_bytes_crc_ok, len); } else { STATS_INC(ble_ll_stats, rx_adv_pdu_crc_ok); STATS_INCN(ble_ll_stats, rx_adv_bytes_crc_ok, len); ble_ll_count_rx_adv_pdus(pdu_type); } } else { if (chan < BLE_PHY_NUM_DATA_CHANS) { STATS_INC(ble_ll_stats, rx_data_pdu_crc_err); STATS_INCN(ble_ll_stats, rx_data_bytes_crc_err, len); } else { STATS_INC(ble_ll_stats, rx_adv_pdu_crc_err); STATS_INCN(ble_ll_stats, rx_adv_bytes_crc_err, len); } } }
int ble_phy_tx(struct os_mbuf *txpdu, uint8_t end_trans) { int rc; uint8_t *dptr; uint8_t *pktptr; uint8_t payload_len; uint32_t state; uint32_t shortcuts; struct ble_mbuf_hdr *ble_hdr; /* Better have a pdu! */ assert(txpdu != NULL); /* * 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(); ble_hdr = BLE_MBUF_HDR_PTR(txpdu); payload_len = ble_hdr->txinfo.pyld_len; #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION) == 1) if (g_ble_phy_data.phy_encrypted) { dptr = (uint8_t *)&g_ble_phy_enc_buf[0]; ++dptr; pktptr = (uint8_t *)&g_ble_phy_tx_buf[0]; NRF_CCM->SHORTS = 1; NRF_CCM->INPTR = (uint32_t)dptr; NRF_CCM->OUTPTR = (uint32_t)pktptr; NRF_CCM->SCRATCHPTR = (uint32_t)&g_nrf_encrypt_scratchpad[0]; NRF_CCM->EVENTS_ERROR = 0; NRF_CCM->MODE = CCM_MODE_LENGTH_Msk; NRF_CCM->CNFPTR = (uint32_t)&g_nrf_ccm_data; NRF_PPI->CHENCLR = PPI_CHEN_CH25_Msk | PPI_CHEN_CH23_Msk; NRF_PPI->CHENSET = PPI_CHEN_CH24_Msk; } else { #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1) NRF_PPI->CHENCLR = PPI_CHEN_CH23_Msk; NRF_AAR->IRKPTR = (uint32_t)&g_nrf_irk_list[0]; #endif dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; ++dptr; pktptr = dptr; } #else #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1) NRF_PPI->CHENCLR = PPI_CHEN_CH23_Msk; #endif dptr = (uint8_t *)&g_ble_phy_tx_buf[0]; ++dptr; pktptr = dptr; #endif /* RAM representation has S0, LENGTH and S1 fields. (3 bytes) */ dptr[0] = ble_hdr->txinfo.hdr_byte; dptr[1] = payload_len; dptr[2] = 0; dptr += 3; NRF_RADIO->PACKETPTR = (uint32_t)pktptr; /* Clear the ready, end and disabled events */ NRF_RADIO->EVENTS_READY = 0; NRF_RADIO->EVENTS_END = 0; NRF_RADIO->EVENTS_DISABLED = 0; /* Enable shortcuts for transmit start/end. */ shortcuts = RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_READY_START_Msk; if (end_trans == BLE_PHY_TRANSITION_TX_RX) { shortcuts |= RADIO_SHORTS_DISABLED_RXEN_Msk; } NRF_RADIO->SHORTS = shortcuts; NRF_RADIO->INTENSET = RADIO_INTENSET_DISABLED_Msk; /* 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; /* If we already started transmitting, abort it! */ state = NRF_RADIO->STATE; if (state != RADIO_STATE_STATE_Tx) { /* Copy data from mbuf into transmit buffer */ 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, payload_len + BLE_LL_PDU_HDR_LEN); rc = BLE_ERR_SUCCESS; } else { ble_phy_disable(); STATS_INC(ble_phy_stats, tx_late); rc = BLE_PHY_ERR_RADIO_STATE; } return rc; }