static void handle_received_frame_irq(void) { /* Actual frame length of received frame. */ uint8_t phy_frame_len; uint8_t *rx_frame_ptr = at86rfx_rx_buffer; /* Perform FCS check for frame validation */ if (CRC16_NOT_VALID == pal_trx_bit_read(SR_RX_CRC_VALID)) { return; } /* Get frame length from transceiver. */ pal_trx_frame_read(&phy_frame_len, LENGTH_FIELD_LEN); /* Check for valid frame length. */ if (phy_frame_len > PHY_MAX_LENGTH) { return; } /* Frame read from transceiver buffer. */ pal_trx_frame_read(rx_frame_ptr, LENGTH_FIELD_LEN + phy_frame_len); /* Set flag indicating received frame to be handled. */ at86rfx_frame_rx = true; set_trx_state(CMD_RX_ON); }
/* * \brief Generates a 16-bit random number used as initial seed for srand() */ void tal_generate_rand_seed(void) { /* * For AT86RF230B bysed systems the random seed is generated by reading *the random contents of the frame buffer after initialization * since there is no tranceiver based random number generator * available. */ static uint8_t data[127]; static uint16_t seed; pal_trx_frame_read(data, 127); for (uint8_t i = 0; i < 127; i++) { seed = seed + data[i]; } srand(seed); }
/* * \brief Handle received frame interrupt * * This function handles transceiver interrupts for received frames and * uploads the frames from the trx. */ void handle_received_frame_irq(void) { uint8_t ed_value; /* Actual frame length of received frame. */ uint8_t phy_frame_len; /* Extended frame length appended by LQI and ED. */ uint8_t ext_frame_length; frame_info_t *receive_frame; uint8_t *frame_ptr; if (tal_rx_buffer == NULL) { Assert("no tal_rx_buffer available" == 0); /* * Although the buffer protection mode is enabled and the receiver has * been switched to PLL_ON, the next incoming frame was faster. * It cannot be handled and is discarded. */ pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_DISABLE); /* Disable buffer protection mode */ pal_timer_delay(2); // Allow pin change to get effective pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_ENABLE); /* Enable buffer protection mode */ return; } receive_frame = (frame_info_t *)BMM_BUFFER_POINTER(tal_rx_buffer); #ifdef PROMISCUOUS_MODE if (tal_pib.PromiscuousMode) { /* Check for valid FCS */ if (pal_trx_bit_read(SR_RX_CRC_VALID) == CRC16_NOT_VALID) { return; } } #endif /* Get ED value; needed to normalize LQI. */ ed_value = pal_trx_reg_read(RG_PHY_ED_LEVEL); /* Get frame length from transceiver. */ phy_frame_len = ext_frame_length = pal_trx_reg_read(RG_TST_RX_LENGTH); /* Check for valid frame length. */ if (phy_frame_len > 127) { return; } /* * The PHY header is also included in the frame (length field), hence the frame length * is incremented. * In addition to that, the LQI and ED value are uploaded, too. */ ext_frame_length += LQI_LEN + ED_VAL_LEN; /* Update payload pointer to store received frame. */ frame_ptr = (uint8_t *)receive_frame + LARGE_BUFFER_SIZE - ext_frame_length; /* * Note: The following code is different from other non-single chip * transceivers, where reading the frame via SPI contains the length field * in the first octet. */ pal_trx_frame_read(frame_ptr, phy_frame_len + LQI_LEN); frame_ptr--; *frame_ptr = phy_frame_len; receive_frame->mpdu = frame_ptr; /* Add ED value at the end of the frame buffer. */ receive_frame->mpdu[phy_frame_len + LQI_LEN + ED_VAL_LEN] = ed_value; #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) /* * Store the timestamp. * The timestamping is only required for beaconing networks * or if timestamping is explicitly enabled. */ receive_frame->time_stamp = tal_rx_timestamp; #endif /* #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */ /* Append received frame to incoming_frame_queue and get new rx buffer. */ qmm_queue_append(&tal_incoming_frame_queue, tal_rx_buffer); /* The previous buffer is eaten up and a new buffer is not assigned yet. */ tal_rx_buffer = bmm_buffer_alloc(LARGE_BUFFER_SIZE); /* Check if receive buffer is available */ if (NULL == tal_rx_buffer) { /* * Turn off the receiver until a buffer is available again. * tal_task() will take care of eventually reactivating it. * Due to ongoing ACK transmission do not force to switch it off. */ /* Do not change the state since buffer protection mode is not re-enabled yet. * Buffer protection will be re-enabled after buffer becomes available */ //set_trx_state(CMD_PLL_ON); tal_rx_on_required = true; } else { /* * Trx returns to RX_AACK_ON automatically, if this was its previous state. * Keep the following as a reminder, if receiver is used with RX_ON instead. */ //pal_trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON); /* * Release the protected buffer and set it again for further protection since * the buffer is available */ pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_DISABLE); /* Disable buffer protection mode */ pal_timer_delay(2); // Allow pin change to get effective pal_trx_bit_write(SR_RX_SAFE_MODE, RX_SAFE_MODE_ENABLE); /* Enable buffer protection mode */ } /* * Clear pending TX_END IRQ: The TX_END IRQ is envoked for the transmission * end of an automatically sent ACK frame. This implementation does not use * this feature. */ pal_trx_irq_flag_clr_tx_end(); }
/** * \brief Interrupt handler for ACK reception * * \param parameter Unused callback parameter */ static void ack_reception_handler_cb(void *parameter) { trx_irq_reason_t trx_irq_cause; if (tal_csma_state == TX_DONE_NO_ACK) { return; /* ack expiration timer has already been fired */ } trx_irq_cause = (trx_irq_reason_t)pal_trx_reg_read(RG_IRQ_STATUS); if (trx_irq_cause & TRX_IRQ_TRX_END) { retval_t timer_status; switch (tal_csma_state) { case FRAME_SENDING_WITH_ACK: set_trx_state(CMD_RX_ON); timer_status = pal_timer_start(TAL_ACK_WAIT_TIMER, TAL_CONVERT_SYMBOLS_TO_US( TAL_ACK_WAIT_DURATION_DEFAULT), TIMEOUT_RELATIVE, (FUNC_PTR)ack_timer_expiry_handler_cb, NULL); if (timer_status == MAC_SUCCESS) { tal_csma_state = WAITING_FOR_ACK; } else if (timer_status == PAL_TMR_ALREADY_RUNNING) { tal_csma_state = WAITING_FOR_ACK; } else { tal_csma_state = TX_DONE_NO_ACK; Assert("timer start failed" == 0); } /* debug pin to switch on: define ENABLE_DEBUG_PINS, *pal_config.h */ PIN_TX_END(); PIN_ACK_WAITING_START(); break; case WAITING_FOR_ACK: { uint8_t ack_frame[ACK_FRAME_LEN + LENGTH_FIELD_LEN]; /* * Read the frame buffer, identify if this is an ACK *frame, * and get the sequence number. * Üpload the frame from the transceiver. */ pal_trx_frame_read(ack_frame, (ACK_FRAME_LEN + LENGTH_FIELD_LEN)); /* Check if the uploaded frame is an ACK frame */ if ((ack_frame[1] & ACK_FRAME) != ACK_FRAME) { /* The received frame is not an ACK frame */ return; } /* check CRC */ if (pal_trx_bit_read(SR_RX_CRC_VALID) != CRC16_VALID) { return; } /* check the sequence number */ if (ack_frame[3] == tal_frame_to_tx[SEQ_NUMBER_POS]) { /* * If we are here, the ACK is valid and matches * the transmitted sequence number. */ pal_timer_stop(TAL_ACK_WAIT_TIMER); #if (_DEBUG_ > 0) if (pal_is_timer_running(TAL_ACK_WAIT_TIMER)) { Assert("Ack timer running" == 0); } #endif /* restore the interrupt handler */ pal_trx_irq_init((FUNC_PTR)trx_irq_handler_cb); pal_trx_irq_en(); if (NULL != tal_rx_buffer) { pal_trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON); } else { tal_rx_on_required = true; } /* debug pin to switch on: define *ENABLE_DEBUG_PINS, pal_config.h */ PIN_ACK_OK_START(); if (ack_frame[1] & FCF_FRAME_PENDING) { tal_csma_state = TX_DONE_FRAME_PENDING; } else { tal_csma_state = TX_DONE_SUCCESS; } /* debug pin to switch on: define *ENABLE_DEBUG_PINS, pal_config.h */ PIN_ACK_OK_END(); PIN_ACK_WAITING_END(); } } break; case FRAME_SENDING_NO_ACK: /* Tx is done */ /* debug pin to switch on: define ENABLE_DEBUG_PINS, *pal_config.h */ PIN_TX_END(); tal_csma_state = TX_DONE_SUCCESS; break; default: Assert("unknown tal_csma_state" == 0); break; } } else { /* other interrupt than TRX_END */ /* no interest in any other interrupt */ return; } parameter = parameter; /* Keep compiler happy. */ }
/** * @brief Handle received frame interrupt * * This function handles transceiver interrupts for received frames and * uploads the frames from the trx. */ void handle_received_frame_irq(void) { uint8_t ed_value; /* Actual frame length of received frame. */ uint8_t phy_frame_len; /* Extended frame length appended by LQI and ED. */ uint8_t ext_frame_length; frame_info_t *receive_frame; uint8_t *frame_ptr; #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) uint32_t timestamp_us; #endif /*if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */ if (tal_rx_buffer == NULL) { ASSERT("no tal_rx_buffer available" == 0); return; } #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) /* * The timestamping is only required for beaconing networks * or if timestamping is explicitly enabled. */ pal_trx_read_timestamp(×tamp_us); #endif /*if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */ receive_frame = (frame_info_t *)BMM_BUFFER_POINTER(tal_rx_buffer); #ifdef PROMISCUOUS_MODE if (tal_pib.PromiscuousMode) { /* Check for valid FCS */ if (pal_trx_bit_read(SR_RX_CRC_VALID) == CRC16_NOT_VALID) { return; } } #endif /* Get ED value; needed to normalize LQI. */ ed_value = pal_trx_reg_read(RG_PHY_ED_LEVEL); /* Get frame length from transceiver. */ pal_trx_frame_read(&phy_frame_len, LENGTH_FIELD_LEN); /* Check for valid frame length. */ if (phy_frame_len > 127) { return; } /* * The PHY header is also included in the frame (length field), hence the frame length * is incremented. * In addition to that, the LQI and ED value are uploaded, too. */ ext_frame_length = phy_frame_len + LENGTH_FIELD_LEN + LQI_LEN + ED_VAL_LEN; /* Update payload pointer to store received frame. */ frame_ptr = (uint8_t *)receive_frame + LARGE_BUFFER_SIZE - ext_frame_length; /* * Note: The following code is different from single chip * transceivers, since reading the frame via SPI contains the length field * in the first octet. */ pal_trx_frame_read(frame_ptr, LENGTH_FIELD_LEN + phy_frame_len + LQI_LEN); receive_frame->mpdu = frame_ptr; /* Add ED value at the end of the frame buffer. */ receive_frame->mpdu[phy_frame_len + LQI_LEN + ED_VAL_LEN] = ed_value; #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) /* * Store the timestamp. * The timestamping is only required for beaconing networks * or if timestamping is explicitly enabled. */ receive_frame->time_stamp = timestamp_us; #endif /* #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */ /* Append received frame to incoming_frame_queue and get new rx buffer. */ qmm_queue_append(&tal_incoming_frame_queue, tal_rx_buffer); /* The previous buffer is eaten up and a new buffer is not assigned yet. */ tal_rx_buffer = bmm_buffer_alloc(LARGE_BUFFER_SIZE); /* Check if receive buffer is available */ if (NULL == tal_rx_buffer) { /* * Turn off the receiver until a buffer is available again. * tal_task() will take care of eventually reactivating it. * Due to ongoing ACK transmission do not force to switch it off. */ set_trx_state(CMD_PLL_ON); tal_rx_on_required = true; } else { /* * Trx returns to RX_AACK_ON automatically, if this was its previous state. * Keep the following as a reminder, if receiver is used with RX_ON instead. */ //pal_trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON); } }
/* * \brief Handle received frame interrupt * * This function handles transceiver interrupts for received frames and * uploads the frames from the trx. */ void handle_received_frame_irq(void) { /* Actual frame length of received frame. */ uint8_t phy_frame_len; /* Extended frame length appended by LQI and ED. */ uint8_t ext_frame_length; frame_info_t *receive_frame; uint8_t *frame_ptr; if (tal_rx_buffer == NULL) { Assert("no tal_rx_buffer available" == 0); /* * Although the buffer protection mode is enabled and the *receiver has * been switched to PLL_ON, the next incoming frame was faster. * It cannot be handled and is discarded. Reading anything from *the * frame resets the buffer protection mode. */ uint8_t dummy; pal_trx_frame_read(&dummy, 1); return; } receive_frame = (frame_info_t *)BMM_BUFFER_POINTER(tal_rx_buffer); #ifdef PROMISCUOUS_MODE if (tal_pib.PromiscuousMode) { /* Check for valid FCS */ if (pal_trx_bit_read(SR_RX_CRC_VALID) == CRC16_NOT_VALID) { return; } } #endif #if (defined ENABLE_TRX_SRAM) || defined(ENABLE_TRX_SRAM_READ) /* Use SRAM read to keep rx safe mode armed. */ pal_trx_sram_read(0x00, &phy_frame_len, LENGTH_FIELD_LEN); /* 0x00: SRAM * offset * address */ #else /* Get frame length from transceiver. */ pal_trx_frame_read(&phy_frame_len, LENGTH_FIELD_LEN); #endif /* Check for valid frame length. */ if (phy_frame_len > 127) { return; } /* * The PHY header is also included in the frame (length field), hence *the frame length * is incremented. * In addition to that, the LQI and ED value are uploaded, too. */ ext_frame_length = phy_frame_len + LENGTH_FIELD_LEN + LQI_LEN + ED_VAL_LEN; /* Update payload pointer to store received frame. */ frame_ptr = (uint8_t *)receive_frame + LARGE_BUFFER_SIZE - ext_frame_length; /* * Note: The following code is different from single chip * transceivers, since reading the frame via SPI contains the length *field * in the first octet. RF233's frame buffer includes ED value too. */ pal_trx_frame_read(frame_ptr, LENGTH_FIELD_LEN + phy_frame_len + LQI_LEN + ED_VAL_LEN); receive_frame->mpdu = frame_ptr; #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) /* * Store the timestamp. * The timestamping is only required for beaconing networks * or if timestamping is explicitly enabled. */ receive_frame->time_stamp = tal_timestamp; #endif /* #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */ /* Append received frame to incoming_frame_queue and get new rx buffer. **/ qmm_queue_append(&tal_incoming_frame_queue, tal_rx_buffer); /* The previous buffer is eaten up and a new buffer is not assigned yet. **/ tal_rx_buffer = bmm_buffer_alloc(LARGE_BUFFER_SIZE); /* Check if receive buffer is available */ if (NULL == tal_rx_buffer) { /* * Turn off the receiver until a buffer is available again. * tal_task() will take care of eventually reactivating it. * Due to ongoing ACK transmission do not force to switch it *off. */ set_trx_state(CMD_PLL_ON); tal_rx_on_required = true; } else { /* * Trx returns to RX_AACK_ON automatically, if this was its *previous state. * Keep the following as a reminder, if receiver is used with *RX_ON instead. */ /* pal_trx_reg_write(RG_TRX_STATE, CMD_RX_AACK_ON); */ } }