/* Configures all the tx mechanisms in preparation for TX. This includes channel, whitening init, length fields, etc. Assumes that the payload is already laid out in RAM buffer. */ uint32_t ble_radio_tx(ble_t * ble_p){ //TODO - check channel range //TODO - check payload length nrf_tx_buffer[0] = ble_p->pdu_type & PDU_TYPE_MASK; if (ble_p->hw_addr_type == HW_ADDR_TYPE_RANDOM) nrf_tx_buffer[0] |= 0x40; nrf_tx_buffer[1] = ble_p->payload_length; _wait_radio_disabled(); NRF_RADIO->PACKETPTR = (uint32_t )&nrf_tx_buffer; _ble_radio_pre_init(ble_p); gpio_set(GPIO_LED1,0); NRF_RADIO->TASKS_TXEN = 1; event_wait_timeout(&radio_end_evt, 10); //todo, check for timeout and bomb. TODO- really need to make this tickless if ((ble_p->scannable) ) { // set up the receive ble_radio_start_rx(ble_p); } return 0; }
/* * gracefully waits for radio to enter disabled state, which is the starting point for * any radio activity when swtiching between rx and tx mode */ static inline uint32_t _wait_radio_disabled(void) { if (NRF_RADIO->STATE != RADIO_STATE_STATE_Disabled) { // Only yield the thread if we need to NRF_RADIO->TASKS_DISABLE = 1; // Just to be safe, hit the stop button event_wait_timeout(&radio_disabled_evt,10); return 0; } event_unsignal(&radio_disabled_evt); // Unsignal the event in case we had a race return 0; }
void ble_radio_start_rx(ble_t * ble_p){ uint32_t d0, d1; _wait_radio_disabled(); nrf_evt_timeout(&radio_end_evt,50); NRF_RADIO->PACKETPTR = (uint32_t)&nrf_rx_buffer; NRF_RADIO->TASKS_RXEN = 1; uint32_t i = event_wait_timeout(&radio_end_evt,4000); if (NRF_RADIO->STATE == RADIO_STATE_STATE_Rx ) { //we didn't get anything NRF_RADIO->TASKS_DISABLE = 1; // shut down radio } else { for (int i = 0 ; i < (nrf_rx_buffer[1]+2) ; i++) { printf("%02X ",nrf_rx_buffer[i]); } printf("\n"); } return 0; }
/* ble_radio_scan_continuous - used for continuous scanning. return val = zero if packet received return val < 0 if due to timeout Uses double buffered rx buffers, returns with ble_p->payload pointing to the buffer, null if due to timeout. Will return, but radio immediately goes back into receive loop. */ uint32_t ble_radio_scan_continuous(ble_t * ble_p, lk_time_t timeout){ uint32_t retval; if ((ble_p->state != BLE_SCANNING)) { printf("Initing scan mode\n"); _wait_radio_disabled(); _ble_radio_scan_init(ble_p); _ble_radio_pre_init(ble_p); NRF_RADIO->TASKS_RXEN = 1; } retval = event_wait_timeout(&radio_end_evt, timeout); if (retval != 0) { ble_p->payload = NULL; ble_p->payload_length = 0; _ble_radio_increment_rx_buffer(); return -1; } else { _ble_get_current_rx_buffer(ble_p); _ble_radio_increment_rx_buffer(); return 0; } }
static int eth_rx_worker(void *arg) { for (;;) { #if 0 status_t event_err = event_wait_timeout(ð.rx_event, 1000); if (event_err == ERR_TIMED_OUT) { /* periodically poll the phys status register */ /* XXX specific to DP83848 */ uint32_t val; /* Read PHY_MISR */ /* seems to take about 30 usecs */ HAL_ETH_ReadPHYRegister(ð.EthHandle, PHY_MISR, &val); /* Check whether the link interrupt has occurred or not */ if (val & PHY_LINK_INTERRUPT) { /* Read PHY_SR*/ HAL_ETH_ReadPHYRegister(ð.EthHandle, PHY_SR, &val); /* Check whether the link is up or down*/ if (val & PHY_LINK_STATUS) { printf("eth: link up\n"); //netif_set_link_up(link_arg->netif); } else { printf("eth: link down\n"); //netif_set_link_down(link_arg->netif); } } } else { #else status_t event_err = event_wait(ð.rx_event); if (event_err >= NO_ERROR) { #endif // XXX probably race with the event here while (HAL_ETH_GetReceivedFrame_IT(ð.EthHandle) == HAL_OK) { LTRACEF("got packet len %u, buffer %p, seg count %u\n", eth.EthHandle.RxFrameInfos.length, (void *)eth.EthHandle.RxFrameInfos.buffer, eth.EthHandle.RxFrameInfos.SegCount); #if WITH_LIB_MINIP /* allocate a pktbuf header, point it at our rx buffer, and pass up the stack */ pktbuf_t *p = pktbuf_alloc_empty(); if (p) { pktbuf_add_buffer(p, (void *)eth.EthHandle.RxFrameInfos.buffer, eth.EthHandle.RxFrameInfos.length, 0, 0, NULL, NULL); p->dlen = eth.EthHandle.RxFrameInfos.length; minip_rx_driver_callback(p); pktbuf_free(p, true); } #endif /* Release descriptors to DMA */ /* Point to first descriptor */ __IO ETH_DMADescTypeDef *dmarxdesc; dmarxdesc = eth.EthHandle.RxFrameInfos.FSRxDesc; /* Set Own bit in Rx descriptors: gives the buffers back to DMA */ for (uint i=0; i< eth.EthHandle.RxFrameInfos.SegCount; i++) { dmarxdesc->Status |= ETH_DMARXDESC_OWN; dmarxdesc = (ETH_DMADescTypeDef *)(dmarxdesc->Buffer2NextDescAddr); } /* Clear Segment_Count */ eth.EthHandle.RxFrameInfos.SegCount =0; /* When Rx Buffer unavailable flag is set: clear it and resume reception */ if ((eth.EthHandle.Instance->DMASR & ETH_DMASR_RBUS) != (uint32_t)RESET) { /* Clear RBUS ETHERNET DMA flag */ eth.EthHandle.Instance->DMASR = ETH_DMASR_RBUS; /* Resume DMA reception */ eth.EthHandle.Instance->DMARPDR = 0; } } } } return 0; } #if WITH_LIB_MINIP status_t stm32_eth_send_minip_pkt(pktbuf_t *p) { LTRACEF("p %p, dlen %zu, eof %u\n", p, p->dlen, p->flags & PKTBUF_FLAG_EOF); DEBUG_ASSERT(p && p->dlen); if (!(p->flags & PKTBUF_FLAG_EOF)) { /* can't handle multi part packets yet */ PANIC_UNIMPLEMENTED; return ERR_NOT_IMPLEMENTED; } status_t err = eth_send(p->data, p->dlen); pktbuf_free(p, true); return err; }
/** * @brief Same as event_wait_timeout(), but without a timeout. */ status_t event_wait(event_t *e) { return event_wait_timeout(e, INFINITE_TIME); }