/** * @brief Timestamp interrupt handler * * This function handles the interrupts handling the timestamp. */ void trx_irq_timestamp_handler_cb(void) { pal_trx_read_timestamp(&tal_timestamp); #ifdef EXACT_TIMESTAMPING /* If exact timestamping is required, a processing delay should be substracted.*/ tal_timestamp -= TRX_IRQ_DELAY_US; #endif }
/* * \brief Transceiver interrupt handler * * This function handles the transceiver generated interrupts. */ void trx_irq_handler_cb(void) { trx_irq_reason_t trx_irq_cause; trx_irq_cause = /* (trx_irq_reason_t)*/ trx_reg_read(RG_IRQ_STATUS); #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) #if (DISABLE_TSTAMP_IRQ == 1) if (trx_irq_cause & TRX_IRQ_2_RX_START) { /* * Get timestamp. * * In case Antenna diversity is used or the utilization of * the Timestamp IRQ is disabled, the timestamp needs to be read * now * the "old-fashioned" way. * * The timestamping is generally only done for * beaconing networks or if timestamping is explicitly enabled. */ pal_trx_read_timestamp(&tal_timestamp); } #endif /* #if (DISABLE_TSTAMP_IRQ == 1) */ #endif /* #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */ if (trx_irq_cause & TRX_IRQ_3_TRX_END) { /* * TRX_END reason depends on if the trx is currently used for * transmission or reception. */ #if ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT)) if ((tal_state == TAL_TX_AUTO) || tal_beacon_transmission) #else if (tal_state == TAL_TX_AUTO) #endif { /* Get the result and push it to the queue. */ if (trx_irq_cause & TRX_IRQ_6_TRX_UR) { handle_tx_end_irq(true); /* see tal_tx.c */ } else { handle_tx_end_irq(false); /* see tal_tx.c */ } } else { /* Other tal_state than TAL_TX_... */ /* Handle rx interrupt. */ handle_received_frame_irq(); /* see tal_rx.c */ } #ifdef ENABLE_RTB #if (RTB_TYPE == RTB_PMU_233R) rtb_update_fec(); #endif /* (RTB_TYPE == RTB_PMU_233R) */ #endif } } /* trx_irq_handler_cb() */
/* * \brief Transceiver interrupt handler * * This function handles the transceiver generated interrupts. */ void trx_irq_handler_cb(void) { trx_irq_reason_t trx_irq_cause; trx_irq_cause = (trx_irq_reason_t)trx_reg_read(RG_IRQ_STATUS); #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) #if (ANTENNA_DIVERSITY == 1) || (DISABLE_TSTAMP_IRQ == 1) if (trx_irq_cause & TRX_IRQ_RX_START) { /* * Get timestamp. * * In case Antenna diversity is used or the utilization of * the Timestamp IRQ is disabled, the timestamp needs to be read * now * the "old-fashioned" way. * * The timestamping is generally only done for * beaconing networks or if timestamping is explicitly enabled. */ pal_trx_read_timestamp(&tal_rx_timestamp); } #endif /* #if (ANTENNA_DIVERSITY == 1) || (DISABLE_TSTAMP_IRQ == 1) */ #endif /* #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */ if (trx_irq_cause & TRX_IRQ_TRX_END) { /* * TRX_END reason depends on if the trx is currently used for * transmission or reception. */ #if ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT)) if ((tal_state == TAL_TX_AUTO) || tal_beacon_transmission) #else if (tal_state == TAL_TX_AUTO) #endif { /* Get the result and push it to the queue. */ if (trx_irq_cause & TRX_IRQ_TRX_UR) { handle_tx_end_irq(true); /* see tal_tx.c */ } else { handle_tx_end_irq(false); /* see tal_tx.c */ } } else { /* Other tal_state than TAL_TX_... */ /* Handle rx interrupt. */ handle_received_frame_irq(); /* see tal_rx.c */ #if (defined SW_CONTROLLED_CSMA) && (defined RX_WHILE_BACKOFF) if (tal_state == TAL_BACKOFF) { pal_timer_stop(TAL_T_BOFF); tal_state = TAL_CSMA_CONTINUE; } #endif } } #if (ANTENNA_DIVERSITY == 1) else if (trx_irq_cause & TRX_IRQ_RX_START) { /* * The antenna that has been selected automatically for the * current frame * reception is set for the ACK transmission too. */ if (trx_bit_read(SR_ANT_SEL) == ANT_SEL_ANTENNA_0) { trx_bit_write(SR_ANT_CTRL, ANT_CTRL_1); } else { /* antenna 1 is in use */ trx_bit_write(SR_ANT_CTRL, ANT_CTRL_2); } } #endif } /* trx_irq_handler_cb() */
/* * \brief Timestamp interrupt handler * * This function handles the interrupts handling the timestamp. * * The timestamping is only required for * - beaconing networks or if timestamping is explicitly enabled, * - and if antenna diversity is NOT enabled, * - and if the time stamp interrupt is not explicitly disabled. */ void trx_irq_timestamp_handler_cb(void) { pal_trx_read_timestamp(&tal_rx_timestamp); }
/* * \brief Handles interrupts issued due to end of transmission */ void handle_tx_end_irq(void) { /* Check if TX_END interrupt, is issued due to automatic ACK *transmission. */ #if ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT)) if ((tal_state != TAL_TX_AUTO) && (!tal_beacon_transmission)) #else if (tal_state != TAL_TX_AUTO) #endif { /* Automatic ACK transmission completed -> No further *processing. */ return; } #if ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT)) if (tal_beacon_transmission) { tal_beacon_transmission = false; if (tal_csma_state == BACKOFF_WAITING_FOR_BEACON) { /* Slotted CSMA has been waiting for a beacon, now it * can continue. */ tal_csma_state = CSMA_HANDLE_BEACON; } } else #endif /* ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT)) */ { #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) /* * Store tx timestamp to frame_info_t structure. * The timestamping is only required for beaconing networks * or if timestamping is explicitly enabled. */ pal_trx_read_timestamp(&mac_frame_ptr->time_stamp); #endif /* #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */ /* Read trac status before enabling RX_AACK_ON. */ trx_trac_status = (trx_trac_status_t)trx_bit_read(SR_TRAC_STATUS); #ifdef BEACON_SUPPORT if (tal_csma_state == FRAME_SENDING) { /* Transmission was * issued by slotted CSMA */ PIN_TX_END(); tal_state = TAL_SLOTTED_CSMA; /* Map status message of transceiver to TAL constants. **/ switch (trx_trac_status) { case TRAC_SUCCESS_DATA_PENDING: PIN_ACK_OK_START(); tal_csma_state = TX_DONE_FRAME_PENDING; break; case TRAC_SUCCESS: PIN_ACK_OK_START(); tal_csma_state = TX_DONE_SUCCESS; break; case TRAC_CHANNEL_ACCESS_FAILURE: PIN_NO_ACK_START(); tal_csma_state = CSMA_ACCESS_FAILURE; break; case TRAC_NO_ACK: PIN_NO_ACK_START(); tal_csma_state = TX_DONE_NO_ACK; break; case TRAC_INVALID: /* Handle this in the same way as *default. */ default: Assert("not handled trac status" == 0); tal_csma_state = CSMA_ACCESS_FAILURE; break; } PIN_ACK_OK_END(); PIN_ACK_WAITING_END(); } else #endif /* BEACON_SUPPORT */ /* Trx has handled the entire transmission incl. CSMA */ { tal_state = TAL_TX_DONE; /* Further handling is done by * tx_done_handling() */ } } /* * After transmission has finished, switch receiver on again. * Check if receive buffer is available. */ if (NULL == tal_rx_buffer) { set_trx_state(CMD_PLL_ON); tal_rx_on_required = true; } else { set_trx_state(CMD_RX_AACK_ON); } }
/* * @brief Transceiver interrupt handler * * This function handles the transceiver generated interrupts. */ void trx_irq_handler_cb(void) { trx_irq_reason_t trx_irq_cause; trx_irq_cause = (trx_irq_reason_t)pal_trx_reg_read(RG_IRQ_STATUS); #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) #if (DISABLE_TSTAMP_IRQ == 1) if (trx_irq_cause & TRX_IRQ_2_RX_START) { /* * Get timestamp. * * In case Antenna diversity is used or the utilization of * the Timestamp IRQ is disabled, the timestamp needs to be read *now * the "old-fashioned" way. * * The timestamping is generally only done for * beaconing networks or if timestamping is explicitly enabled. */ pal_trx_read_timestamp(&tal_rx_timestamp); } #endif /* #if (DISABLE_TSTAMP_IRQ == 1) */ #endif /* #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */ if (trx_irq_cause & TRX_IRQ_3_TRX_END) { /* * TRX_END reason depends on if the trx is currently used for * transmission or reception. */ #if ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT)) if ((tal_state == TAL_TX_AUTO) || tal_beacon_transmission) #else if (tal_state == TAL_TX_AUTO) #endif { /* Get the result and push it to the queue. */ if (trx_irq_cause & TRX_IRQ_6_TRX_UR) { handle_tx_end_irq(true); /* see tal_tx.c */ } else { handle_tx_end_irq(false); /* see tal_tx.c */ } } else { /* Other tal_state than TAL_TX_... */ /* Handle rx interrupt. */ handle_received_frame_irq(); /* see tal_rx.c */ #if (defined SW_CONTROLLED_CSMA) && (defined RX_WHILE_BACKOFF) if (tal_state == TAL_BACKOFF) { pal_timer_stop(TAL_T_BOFF); tal_state = TAL_CSMA_CONTINUE; } #endif } } #if (_DEBUG_ > 0) /* Other IRQ than TRX_END */ if (trx_irq_cause != TRX_IRQ_3_TRX_END) { /* PLL_LOCK interrupt migth be set, because poll mode is *enabled. */ /* * if (trx_irq_cause & TRX_IRQ_0_PLL_LOCK) * { * Assert("unexpected IRQ: TRX_IRQ_0_PLL_LOCK" == 0); * } */ if (trx_irq_cause & TRX_IRQ_1_PLL_UNLOCK) { Assert("unexpected IRQ: TRX_IRQ_1_PLL_UNLOCK" == 0); } /* RX_START interrupt migth be set, because poll mode is *enabled. */ /* * if (trx_irq_cause & TRX_IRQ_2_RX_START) * { * Assert("unexpected IRQ: TRX_IRQ_2_RX_START" == 0); * } */ if (trx_irq_cause & TRX_IRQ_4_CCA_ED_DONE) { Assert("unexpected IRQ: TRX_IRQ_4_CCA_ED_DONE" == 0); } /* AMI interrupt might set, because poll mode is enabled. */ /* * if (trx_irq_cause & TRX_IRQ_5_AMI) * { * Assert("unexpected IRQ: TRX_IRQ_5_AMI" == 0); * } */ if (trx_irq_cause & TRX_IRQ_6_TRX_UR) { Assert("unexpected IRQ: TRX_IRQ_6_TRX_UR" == 0); } if (trx_irq_cause & TRX_IRQ_7_BAT_LOW) { Assert("unexpected IRQ: TRX_IRQ_7_BAT_LOW" == 0); } } #endif } /* trx_irq_handler_cb() */
/* * \brief Handles interrupts issued due to end of transmission * * \param underrun_occured true if under-run has occurred */ void handle_tx_end_irq(bool underrun_occured) { #if ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT)) if (tal_beacon_transmission) { tal_beacon_transmission = false; if (tal_csma_state == BACKOFF_WAITING_FOR_BEACON) { /* Slotted CSMA has been waiting for a beacon, now it * can continue. */ tal_csma_state = CSMA_HANDLE_BEACON; } } else #endif /* ((MAC_START_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT)) */ { #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) /* * Store tx timestamp to frame_info_t structure. * The timestamping is only required for beaconing networks * or if timestamping is explicitly enabled. */ #if (DISABLE_TSTAMP_IRQ == 0) /* * The Tx timestamp is stored during the timestamp interrupt * at DIG2. */ mac_frame_ptr->time_stamp = tal_timestamp; #else { uint32_t time_stamp_temp = 0; pal_trx_read_timestamp(&time_stamp_temp); mac_frame_ptr->time_stamp = time_stamp_temp; } #endif #endif /* #if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */ /* Read trac status before enabling RX_AACK_ON. */ if (underrun_occured) { trx_trac_status = TRAC_INVALID; } else { trx_trac_status = /*(trx_trac_status_t)*/ trx_bit_read( SR_TRAC_STATUS); } #ifdef BEACON_SUPPORT if (tal_csma_state == FRAME_SENDING) { /* Transmission was * issued by slotted CSMA **/ PIN_TX_END(); tal_state = TAL_SLOTTED_CSMA; /* Map status message of transceiver to TAL constants. **/ switch (trx_trac_status) { case TRAC_SUCCESS_DATA_PENDING: PIN_ACK_OK_START(); tal_csma_state = TX_DONE_FRAME_PENDING; break; case TRAC_SUCCESS: PIN_ACK_OK_START(); tal_csma_state = TX_DONE_SUCCESS; break; case TRAC_CHANNEL_ACCESS_FAILURE: PIN_NO_ACK_START(); tal_csma_state = CSMA_ACCESS_FAILURE; break; case TRAC_NO_ACK: PIN_NO_ACK_START(); tal_csma_state = TX_DONE_NO_ACK; break; case TRAC_INVALID: /* Handle this in the same way as * default. */ default: Assert("not handled trac status" == 0); tal_csma_state = CSMA_ACCESS_FAILURE; break; } PIN_ACK_OK_END(); PIN_ACK_WAITING_END(); } else #endif /* BEACON_SUPPORT */ /* Trx has handled the entire transmission incl. CSMA */ { if (tal_sw_retry_no_csma_ca && tal_sw_retry_count && TRAC_NO_ACK == trx_trac_status) { tal_trx_status_t trx_status; do { trx_status = set_trx_state( CMD_TX_ARET_ON); } while (trx_status != TX_ARET_ON); /* Toggle the SLP_TR pin triggering *transmission. */ TRX_SLP_TR_HIGH(); PAL_WAIT_65_NS(); TRX_SLP_TR_LOW(); if (--tal_sw_retry_count == 0) { tal_sw_retry_no_csma_ca = false; } } else { tal_state = TAL_TX_DONE; /* Further handling is * done by * tx_done_handling() **/ } } } /* * After transmission has finished, switch receiver on again. * Check if receive buffer is available. */ if (NULL == tal_rx_buffer) { set_trx_state(CMD_PLL_ON); tal_rx_on_required = true; } else { set_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) { 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); } }