static void ble_phy_rx_start_isr(void) { int rc; uint32_t state; struct ble_mbuf_hdr *ble_hdr; /* Clear events and clear interrupt */ NRF_RADIO->EVENTS_ADDRESS = 0; NRF_RADIO->INTENCLR = RADIO_INTENCLR_ADDRESS_Msk; /* Wait to get 1st byte of frame */ while (1) { state = NRF_RADIO->STATE; if (NRF_RADIO->EVENTS_BCMATCH != 0) { break; } /* * 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; } } /* Initialize flags, channel and state in ble header at rx start */ ble_hdr = &g_ble_phy_data.rxhdr; 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] - os_cputime_usecs_to_ticks(BLE_TX_LEN_USECS_M(NRF_RX_START_OFFSET)); /* Call Link Layer receive start function */ rc = ble_ll_rx_start((uint8_t *)&g_ble_phy_rx_buf[0] + 3, g_ble_phy_data.phy_chan, &g_ble_phy_data.rxhdr); 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; #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1) /* Must start aar if we need to */ if (g_ble_phy_data.phy_privacy) { NRF_RADIO->EVENTS_BCMATCH = 0; NRF_PPI->CHENSET = PPI_CHEN_CH23_Msk; NRF_RADIO->BCC = (BLE_DEV_ADDR_LEN + BLE_LL_PDU_HDR_LEN) * 8; } #endif } 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) { int rc; uint8_t transition; uint8_t crcok; uint32_t irq_en; uint32_t state; uint32_t wfr_time; 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) { /* Better be in TX state! */ assert(g_ble_phy_data.phy_state == BLE_PHY_STATE_TX); ble_ll_log(BLE_LL_LOG_ID_PHY_TXEND, g_ble_phy_txrx_buf[1], 0, NRF_TIMER0->CC[2]); /* Clear events and clear interrupt on disabled event */ NRF_RADIO->EVENTS_DISABLED = 0; NRF_RADIO->INTENCLR = RADIO_INTENCLR_DISABLED_Msk; NRF_RADIO->EVENTS_END = 0; state = NRF_RADIO->SHORTS; transition = g_ble_phy_data.phy_transition; if (transition == BLE_PHY_TRANSITION_TX_RX) { /* Clear the rx started flag */ g_ble_phy_data.phy_rx_started = 0; /* Packet pointer needs to be reset. */ if (g_ble_phy_data.rxpdu != NULL) { NRF_RADIO->PACKETPTR = (uint32_t)g_ble_phy_data.rxpdu->om_data; /* I want to know when 1st byte received (after address) */ NRF_RADIO->BCC = 8; /* in bits */ NRF_RADIO->EVENTS_ADDRESS = 0; NRF_RADIO->EVENTS_DEVMATCH = 0; NRF_RADIO->EVENTS_BCMATCH = 0; NRF_RADIO->EVENTS_RSSIEND = 0; NRF_RADIO->SHORTS = RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_ADDRESS_BCSTART_Msk | RADIO_SHORTS_ADDRESS_RSSISTART_Msk | RADIO_SHORTS_DISABLED_RSSISTOP_Msk; NRF_RADIO->INTENSET = RADIO_INTENSET_ADDRESS_Msk; g_ble_phy_data.phy_state = BLE_PHY_STATE_RX; } else { /* Disable the phy */ ++g_ble_phy_stats.no_bufs; ble_phy_disable(); } /* * Enable the wait for response timer. Note that cc #2 on * timer 0 contains the transmit end time */ wfr_time = NRF_TIMER0->CC[2]; 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! */ assert(transition == BLE_PHY_TRANSITION_NONE); } /* Call transmit end callback */ if (g_ble_phy_data.txend_cb) { g_ble_phy_data.txend_cb(g_ble_phy_data.txend_arg); } } /* 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; 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; } /* * If state is disabled, we should have the BCMATCH. If not, * something is wrong! */ if (state == RADIO_STATE_STATE_Disabled) { NRF_RADIO->INTENCLR = NRF52_RADIO_IRQ_MASK_ALL; NRF_RADIO->SHORTS = 0; goto 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; /* 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) { g_ble_phy_data.phy_rx_started = 1; if (rc > 0) { /* We need to go from disabled to TXEN */ NRF_RADIO->SHORTS = RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_READY_START_Msk | RADIO_SHORTS_DISABLED_TXEN_Msk; } else { NRF_RADIO->SHORTS = RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_READY_START_Msk; } /* Set rx end ISR enable */ NRF_RADIO->INTENSET = RADIO_INTENSET_END_Msk; } else { /* Disable PHY */ ble_phy_disable(); irq_en = 0; ++g_ble_phy_stats.rx_aborts; } /* Count rx starts */ ++g_ble_phy_stats.rx_starts; } /* 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]; /* Count PHY crc errors and valid packets */ crcok = (uint8_t)NRF_RADIO->CRCSTATUS; if (!crcok) { ++g_ble_phy_stats.rx_crc_err; } else { ++g_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; rc = ble_ll_rx_end(rxpdu, ble_hdr); if (rc < 0) { /* Disable the PHY. */ ble_phy_disable(); } } phy_isr_exit: /* Ensures IRQ is cleared */ state = NRF_RADIO->SHORTS; /* Count # of interrupts */ ++g_ble_phy_stats.phy_isrs; }