Exemple #1
0
retval_t mac_timers_stop(void)
{
#if (NUMBER_OF_MAC_TIMERS > 0)
#ifdef BEACON_SUPPORT
	pal_timer_stop(T_Beacon_Tracking_Period);
	pal_timer_stop(T_Superframe);
	pal_timer_stop(T_Missed_Beacon);
    #if (MAC_START_REQUEST_CONFIRM == 1)
	pal_timer_stop(T_Beacon);
	pal_timer_stop(T_Beacon_Preparation);
    #endif /* (MAC_START_REQUEST_CONFIRM == 1) */
#ifdef GTS_SUPPORT
	pal_timer_stop(T_CAP);
#endif /* GTS_SUPPORT */
#endif  /* BEACON_SUPPORT / No BEACON_SUPPORT */

#if (MAC_INDIRECT_DATA_BASIC == 1)
	pal_timer_stop(T_Poll_Wait_Time);
    #if (MAC_INDIRECT_DATA_FFD == 1)
	pal_timer_stop(T_Data_Persistence);
    #endif  /* (MAC_INDIRECT_DATA_FFD == 1) */
#endif  /* (MAC_INDIRECT_DATA_BASIC == 1) */

#if (MAC_SCAN_SUPPORT == 1)
	pal_timer_stop(T_Scan_Duration);
#endif  /* MAC_SCAN_SUPPORT */

#if (MAC_RX_ENABLE_SUPPORT == 1)
	pal_timer_stop(T_Rx_Enable);
#endif  /* MAC_RX_ENABLE_SUPPORT */
#endif /* (NUMBER_OF_MAC_TIMERS != 0) */
	return MAC_SUCCESS;
}
static void tal_timers_stop(void)
{
#if (NUMBER_OF_TAL_TIMERS > 0)
#ifdef BEACON_SUPPORT
	/* Beacon Support */
#ifdef ENABLE_FTN_PLL_CALIBRATION
	pal_timer_stop(TAL_CSMA_CCA);
	pal_timer_stop(TAL_CSMA_BEACON_LOSS_TIMER);
	pal_timer_stop(TAL_CALIBRATION);
#ifdef SW_CONTROLLED_CSMA
	pal_timer_stop(TAL_T_BOFF);
#endif

#else
	pal_timer_stop(TAL_CSMA_CCA);
	pal_timer_stop(TAL_CSMA_BEACON_LOSS_TIMER);
#ifdef SW_CONTROLLED_CSMA
	pal_timer_stop(TAL_T_BOFF);
#endif
#endif  /* ENABLE_FTN_PLL_CALIBRATION */
#else /* No BEACON_SUPPORT */
#ifdef ENABLE_FTN_PLL_CALIBRATION
	pal_timer_stop(TAL_CALIBRATION);
#ifdef SW_CONTROLLED_CSMA
	pal_timer_stop(TAL_T_BOFF);
#endif

#else
#ifdef SW_CONTROLLED_CSMA
	pal_timer_stop(TAL_T_BOFF);
#endif
#endif  /* ENABLE_FTN_PLL_CALIBRATION */
#endif  /* BEACON_SUPPORT */
#endif  /*  (NUMBER_OF_TAL_TIMERS > 0) */
}
Exemple #3
0
/**
 * @brief Sets the transceiver to sleep
 *
 * This function sets the transceiver to sleep state.
 *
 * @param mode Defines sleep mode of transceiver SLEEP or PHY_TRX_OFF)
 *
 * @return   TAL_BUSY - The transceiver is busy in TX or RX
 *           MAC_SUCCESS - The transceiver is put to sleep
 *           TAL_TRX_ASLEEP - The transceiver is already asleep
 *           MAC_INVALID_PARAMETER - The specified sleep mode is not supported
 */
retval_t tal_trx_sleep(sleep_mode_t mode)
{
    tal_trx_status_t trx_status;

    /* Current transceiver only supports SLEEP_MODE_1 mode. */
    if (SLEEP_MODE_1 != mode)
    {
        return MAC_INVALID_PARAMETER;
    }

    if (tal_trx_status == TRX_SLEEP)
    {
        return TAL_TRX_ASLEEP;
    }

    /* Device can be put to sleep only when the TAL is in IDLE state. */
    if (TAL_IDLE != tal_state)
    {
        return TAL_BUSY;
    }

    tal_rx_on_required = false;

    /*
     * First set trx to TRX_OFF.
     * If trx is busy, like ACK transmission, do not interrupt it.
     */
    do
    {
        trx_status = set_trx_state(CMD_TRX_OFF);
    }
    while (trx_status != TRX_OFF);

    pal_timer_source_select(TMR_CLK_SRC_DURING_TRX_SLEEP);

    trx_status = set_trx_state(CMD_SLEEP);

#ifdef ENABLE_FTN_PLL_CALIBRATION
    /*
     * Stop the calibration timer now.
     * The timer will be restarted during wake-up.
     */
    pal_timer_stop(TAL_CALIBRATION);
#endif  /* ENABLE_FTN_PLL_CALIBRATION */

    if (trx_status == TRX_SLEEP)
    {
#ifdef STB_ON_SAL
#if (SAL_TYPE == AT86RF2xx)
        stb_restart();
#endif
#endif
        return MAC_SUCCESS;
    }
    else
    {
        /* State could not be set due to TAL_BUSY state. */
        return TAL_BUSY;
    }
}
Exemple #4
0
/**
 * @brief Processes a data response to an MLME-POLL.request
 *
 * This function processes a data response to an MLME-POLL.request.
 * Our coordinator has responded with a data frame. It is checked
 * whether any data has been received, and the appropriate
 * MLME-POLL.confirm message is constructed.
 */
void mac_process_data_response(void)
{
	uint8_t status;

	if (FCF_FRAMETYPE_BEACON == mac_parse_data.frame_type) {
		/*
		 * Node is currently in polling state, so only command or data
		 * frames
		 * are of interest.
		 * This is an unexpected frame type, do nothing.
		 * Note. Ack frames are not uploaded to this point.
		 * All subsequent actions are not to be done now.
		 * Instead the timer will expire and initiate the proper stuff.
		 */
		return;
	} else {
		/* Stop the MaxFrameResponseTime timer */
		pal_timer_stop(T_Poll_Wait_Time);

#if (_DEBUG_ > 0)
		if (pal_is_timer_running(T_Poll_Wait_Time)) {
			Assert("Frame resp tmr running" == 0);
		}
#endif

		/*
		 * For received command frames (Association response or
		 * disassociation notification) and for data frames with zero
		 * payload length the potential status for the poll.confirm
		 * message
		 * is supposed to be "No data".
		 */
		status = MAC_NO_DATA;

		if ((FCF_FRAMETYPE_DATA == mac_parse_data.frame_type) &&
				(mac_parse_data.mac_payload_length > 0)
				) {
			/*
			 * For received data frames with non-zero payload length
			 * the potential status for the poll.confirm message is
			 * supposed to be "Success".
			 */
			status = MAC_SUCCESS;
		}
	}

	if (MAC_POLL_EXPLICIT == mac_poll_state) {
		/*
		 * Data is received on explicit poll request, hence generate the
		 * poll confirm using
		 * the buffer which was stored in mac_conf_buf_ptr.
		 */
		gen_mlme_poll_conf((buffer_t *)mac_conf_buf_ptr, status);
	}

	/* MAC was busy during poll. */
	MAKE_MAC_NOT_BUSY();

	mac_poll_state = MAC_POLL_IDLE;
} /* mac_process_data_response() */
Exemple #5
0
/*
 * @brief helper function to start missed beacon timer
 */
void mac_start_missed_beacon_timer(void)
{
    uint32_t sync_loss_time;
    uint8_t timer_status;

    /* Stop the missed beacon timer. */
    pal_timer_stop(T_Missed_Beacon);

#if (DEBUG > 0)
    if (pal_is_timer_running(T_Missed_Beacon))
    {
        ASSERT("Missed BCN tmr running" == 0);
    }
#endif

    /* Calculate the time allowed for missed beacons. */
    if (tal_pib.BeaconOrder < NON_BEACON_NWK)
    {
        /*
         * This the regualar case where we already have a Beacon Order.
         * In this case the Sync Loss time is a function of the actual
         * Beacon Order.
         */
        sync_loss_time = TAL_GET_BEACON_INTERVAL_TIME(tal_pib.BeaconOrder);
    }
    else
    {
        /*
         * This the "pathological" case where we don NOT have a Beacon Order.
         * This happens regularly in case of synchronization before association
         * if the Beacon Order was not set be the network layer or application.
         *
         * In this case the Sync Loss time is based on the highest possible
         * Beacon Order, which is 15 - 1, since 15 means no Beacon network.
         */
        sync_loss_time = TAL_GET_BEACON_INTERVAL_TIME(NON_BEACON_NWK - 1);
    }

    sync_loss_time *= aMaxLostBeacons;

    sync_loss_time = TAL_CONVERT_SYMBOLS_TO_US(sync_loss_time);

    timer_status = pal_timer_start(T_Missed_Beacon,
                                   sync_loss_time,
                                   TIMEOUT_RELATIVE,
                                   (FUNC_PTR)mac_t_missed_beacons_cb,
                                   NULL);

    if (MAC_SUCCESS != timer_status)
    {
#if (DEBUG > 0)
        ASSERT(MAC_SUCCESS == timer_status);
#endif
        /* Sync timer could not be started hence report sync-loss */
        mac_sync_loss(MAC_BEACON_LOSS);
    }
}
Exemple #6
0
/*
 * \brief Sets the transceiver to sleep
 *
 * This function sets the transceiver to sleep state.
 *
 * \param mode Defines sleep mode of transceiver SLEEP or PHY_TRX_OFF)
 *
 * \return   TAL_BUSY - The transceiver is busy in TX or RX
 *           MAC_SUCCESS - The transceiver is put to sleep
 *           TAL_TRX_ASLEEP - The transceiver is already asleep
 *           MAC_INVALID_PARAMETER - The specified sleep mode is not supported
 */
retval_t tal_trx_sleep(sleep_mode_t mode)
{
	tal_trx_status_t trx_status;

	/* Current transceiver only supports SLEEP_MODE_1 mode. */
	if (SLEEP_MODE_1 != mode) {
		return MAC_INVALID_PARAMETER;
	}

	if (tal_trx_status == TRX_SLEEP) {
		return TAL_TRX_ASLEEP;
	}

	/* Device can be put to sleep only when the TAL is in IDLE state. */
	if (TAL_IDLE != tal_state) {
		return TAL_BUSY;
	}

	tal_rx_on_required = false;

	/*
	 * First set trx to TRX_OFF.
	 * If trx is busy, like ACK transmission, do not interrupt it.
	 */
	do {
		trx_status = set_trx_state(CMD_TRX_OFF);
	} while (trx_status != TRX_OFF);

#ifndef NO_32KHZ_CRYSTAL
	/* Do not set to SLEEP to keep clock source for symbol counter alive. */
	trx_status = set_trx_state(CMD_SLEEP);
#else
	/* Pretend that trx is in SLEEP - for this function only. */
	trx_status = TRX_SLEEP;
#endif

#ifdef ENABLE_FTN_PLL_CALIBRATION

	/*
	 * Stop the calibration timer now.
	 * The timer will be restarted during wake-up.
	 */
	pal_timer_stop(TAL_CALIBRATION);
#endif  /* ENABLE_FTN_PLL_CALIBRATION */

	if (trx_status == TRX_SLEEP) {
#ifdef STB_ON_SAL
		stb_restart();
#endif
		return MAC_SUCCESS;
	} else {
		/* State could not be set due to TAL_BUSY state. */
		return TAL_BUSY;
	}
}
/*
 * @brief Internal function to handle immediate RX_ON
 *
 * This function immediately enables the receiver with the given
 * RxOnDuration time in symbols from now.
 *
 * @param rx_on_duration_symbols Duration in symbols that the reciever is
 *                               switched on.
 */
static void handle_rx_on(uint32_t rx_on_duration_symbols, uint8_t *m)
{
    retval_t timer_status;
    uint8_t rx_enable_status = mac_rx_enable();

    /*
     * TODO: Once it is possible to restart a timer even if it is
     * already running, this could be improved by simply calling
     * function pal_timer_start() without this previous check using
     * function pal_is_timer_running().
     */
    if (pal_is_timer_running(T_Rx_Enable))
    {
        /*
         * Rx-Enable timer is already running, so we need to stopp it first
         * before it will be started.
         */
        pal_timer_stop(T_Rx_Enable);
    }

    /*
     * Start timer for the Rx On duration of the radio being on
     * in order to switch it off later again.
     */
    timer_status =
        pal_timer_start(T_Rx_Enable,
                        TAL_CONVERT_SYMBOLS_TO_US(rx_on_duration_symbols),
                        TIMEOUT_RELATIVE,
                        (FUNC_PTR())mac_t_rx_off_cb,
                        NULL);

    ASSERT(MAC_SUCCESS == timer_status);

    /*
     * Send the confirm immediately depending on the status of
     * the timer start and the Rx Status
     */
    if (MAC_SUCCESS != timer_status)
    {
        gen_rx_enable_conf((buffer_t *)m, (uint8_t)MAC_INVALID_PARAMETER);
        /* Do house-keeeping and turn radio off. */
        mac_t_rx_off_cb(NULL);
    }
    else if (PHY_RX_ON != rx_enable_status)
    {
        gen_rx_enable_conf((buffer_t *)m, (uint8_t)MAC_TX_ACTIVE);
    }
    else
    {
        gen_rx_enable_conf((buffer_t *)m, (uint8_t)MAC_SUCCESS);
    }

    return;
}
Exemple #8
0
/**
 * @brief LED handling including timer control .
 */
static void led_handling(void *callback_parameter)
{
    switch (node_status)
    {
        case PUSH_BUTTON_PAIRING:
        case ALL_IN_ONE_START:
            pal_timer_start(T_LED_TIMER,
                            PAIR_WAIT_PERIOD,
                            TIMEOUT_RELATIVE,
                            (FUNC_PTR)led_handling,
                            NULL);
            pal_led(LED_NWK_SETUP, LED_TOGGLE);
            break;

        default:
            pal_timer_stop(T_LED_TIMER);
            pal_led(LED_DATA, LED_OFF);
            pal_led(LED_NWK_SETUP, LED_OFF);
            break;
    }

    /* Keep compiler happy */
    UNUSED(callback_parameter);
}
Exemple #9
0
/*
 * \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() */
Exemple #10
0
/**
 * @brief Depending on received frame the appropriate function is called
 *
 * @param msg Pointer to the buffer header.
 */
void mac_process_tal_data_ind(uint8_t *msg)
{
	buffer_t *buf_ptr = (buffer_t *)msg;
	frame_info_t *frameptr = (frame_info_t *)BMM_BUFFER_POINTER(buf_ptr);
	bool processed_tal_data_indication = false;

	mac_parse_data.mpdu_length = frameptr->mpdu[0];

	/* First extract LQI since this is already needed in Promiscuous Mode.
	**/
	mac_parse_data.ppdu_link_quality
		= frameptr->mpdu[mac_parse_data.mpdu_length + LQI_LEN];

#ifdef PROMISCUOUS_MODE
	if (tal_pib.PromiscuousMode) {
		/*
		 * In promiscuous mode all received frames are forwarded to the
		 * higher layer or application my means of MCPS_DATA.indication
		 * primitives.
		 */
		prom_mode_rx_frame(buf_ptr, frameptr);
		return;
	}

#endif  /* PROMISCUOUS_MODE */

	if (!parse_mpdu(frameptr)) {
		/* Frame parsing failed */
		bmm_buffer_free(buf_ptr);
		return;
	}

	/* Check if the MAC is busy processing the previous requests */
	if (mac_busy) {
		/*
		 * If MAC has to process an incoming frame that requires a
		 * response
		 * (i.e. beacon request and data request) then process this
		 * operation
		 * once the MAC has become free. Put the request received back
		 * into the
		 * MAC internal event queue.
		 */
		if (FCF_FRAMETYPE_MAC_CMD == mac_parse_data.frame_type) {
			if (DATAREQUEST == mac_parse_data.mac_command ||
					BEACONREQUEST ==
					mac_parse_data.mac_command) {
				qmm_queue_append(&tal_mac_q, buf_ptr);
				return;
			}
		}
	}

	switch (mac_poll_state) {
	case MAC_POLL_IDLE:

		/*
		 * We are in no transient state.
		 * Now are either in a non-transient MAC state or scanning.
		 */
		if (MAC_SCAN_IDLE == mac_scan_state) {
			/*
			 * Continue with handling the "real" non-transient MAC
			 * states now.
			 */
			processed_tal_data_indication
				= process_data_ind_not_transient(
					buf_ptr, frameptr);
		}

#if (MAC_SCAN_SUPPORT == 1)
		else {
			/* Scanning is ongoing. */
			processed_tal_data_indication
				= process_data_ind_scanning(buf_ptr);
		}
#endif /* (MAC_SCAN_SUPPORT == 1) */
		break;

#if (MAC_INDIRECT_DATA_BASIC == 1)

	/*
	 * This is the 'wait for data' state after either
	 * explicit poll or implicit poll.
	 */
	case MAC_POLL_EXPLICIT:
	case MAC_POLL_IMPLICIT:

		/*
		 * Function mac_process_data_response() resets the
		 * MAC poll state.
		 */
		mac_process_data_response();

		switch (mac_parse_data.frame_type) {
		case FCF_FRAMETYPE_MAC_CMD:
		{
			switch (mac_parse_data.mac_command) {
#if (MAC_ASSOCIATION_INDICATION_RESPONSE == 1)
			case ASSOCIATIONREQUEST:
				mac_process_associate_request(buf_ptr);
				processed_tal_data_indication = true;
				break;
#endif /* (MAC_ASSOCIATION_INDICATION_RESPONSE == 1) */

#if (MAC_DISASSOCIATION_BASIC_SUPPORT == 1)
			case DISASSOCIATIONNOTIFICATION:
			{
				mac_process_disassociate_notification(buf_ptr);

				processed_tal_data_indication = true;

				/*
				 * Device needs to scan for networks again,
				 * go into idle mode and reset variables
				 */
				mac_idle_trans();
			}
			break;
#endif /* (MAC_DISASSOCIATION_BASIC_SUPPORT == 1) */

			case DATAREQUEST:
#if (MAC_INDIRECT_DATA_FFD == 1)
				if (indirect_data_q.size > 0) {
					mac_process_data_request(buf_ptr);
					processed_tal_data_indication = true;
				} else {
					mac_handle_tx_null_data_frame();
				}

#endif  /*  (MAC_INDIRECT_DATA_FFD == 1) */
				break;

			case PANIDCONFLICTNOTIFICAION:
				break;

#if (MAC_ORPHAN_INDICATION_RESPONSE == 1)
			case ORPHANNOTIFICATION:
				mac_process_orphan_notification(buf_ptr);
				processed_tal_data_indication = true;
				break;
#endif /* (MAC_ORPHAN_INDICATION_RESPONSE == 1) */

#if (MAC_START_REQUEST_CONFIRM == 1)
			case BEACONREQUEST:
				if (MAC_COORDINATOR == mac_state) {
					/*
					 * Only a Coordinator can both poll and
					 * AND answer beacon request frames.
					 * PAN Coordinators do not poll;
					 * End devices do not answer beacon
					 * requests.
					 */
					mac_process_beacon_request(buf_ptr);
					processed_tal_data_indication = true;
				}
				break;
#endif /* (MAC_START_REQUEST_CONFIRM == 1) */

#if (MAC_SYNC_LOSS_INDICATION == 1)
			case COORDINATORREALIGNMENT:

				/*
				 * Received coordinator realignment frame for
				 * entire PAN.
				 */
				mac_process_coord_realign(buf_ptr);
				processed_tal_data_indication = true;
				break;
#endif  /* (MAC_SYNC_LOSS_INDICATION == 1) */

			default:
#if (_DEBUG_ > 0)
				Assert(
						"Unsupported MAC frame in state MAC_EXPLICIT_POLL or MAC_POLL_IMPLICIT" ==
						0);
#endif
				break;
			}
		}
		break; /* case FCF_FRAMETYPE_MAC_CMD: */

		case FCF_FRAMETYPE_DATA:
			mac_process_data_frame(buf_ptr);
			processed_tal_data_indication = true;
			break;

		default:
			break;
		}
		break;
		/* MAC_POLL_EXPLICIT, MAC_POLL_IMPLICIT */
#endif /* (MAC_INDIRECT_DATA_BASIC == 1) */

#if (MAC_ASSOCIATION_REQUEST_CONFIRM == 1)
	case MAC_AWAIT_ASSOC_RESPONSE:

		/*
		 * We are either expecting an association reponse frame
		 * or a null data frame.
		 */
		if ((FCF_FRAMETYPE_MAC_CMD == mac_parse_data.frame_type) &&
				(ASSOCIATIONRESPONSE ==
				mac_parse_data.mac_command)
				) {
			/* This is the expected association response frame. */
			pal_timer_stop(T_Poll_Wait_Time);

#if (_DEBUG_ > 0)
			if (pal_is_timer_running(T_Poll_Wait_Time)) {
				Assert(
						"T_Poll_Wait_Time tmr during association running" ==
						0);
			}

#endif
			mac_process_associate_response(buf_ptr);
			processed_tal_data_indication = true;
		} else if (FCF_FRAMETYPE_DATA == mac_parse_data.frame_type) {
			mac_process_data_frame(buf_ptr);
			processed_tal_data_indication = true;
		}

		break;
		/*  MAC_AWAIT_ASSOC_RESPONSE */
#endif /* (MAC_ASSOCIATION_REQUEST_CONFIRM == 1) */

	default:
#if (_DEBUG_ > 0)
		Assert("Received frame in unsupported MAC poll state" == 0);
#endif
		break;
	}

	/* If message is not processed */
	if (!processed_tal_data_indication) {
		bmm_buffer_free(buf_ptr);
	}
} /* mac_process_tal_data_ind() */
/**
 * @brief Implement the MLME-RX-ENABLE.request primitive.
 *
 * The MLME-RX-ENABLE.request primitive is generated by the next
 * higher layer and issued to MAC to enable the receiver for a
 * fixed duration, at a time relative to the start of the current or
 * next superframe on a beacon-enabled PAN or immediately on a
 * nonbeacon-enabled PAN. The receiver is enabled exactly once per
 * primitive request.
 *
 * @param m Pointer to the MLME-RX-ENABLE.request message
 */
void mlme_rx_enable_request(uint8_t *m)
{
    mlme_rx_enable_req_t *rxe;

    rxe = (mlme_rx_enable_req_t *)BMM_BUFFER_POINTER((buffer_t *)m);

    /* If RxOnDuration is zero, the receiver shall be disabled */
    if (0 == rxe->RxOnDuration)
    {
        /*
         * Turn the radio off. This is doney by calling the
         * same function as for the expiration of the Rx on timer.
         */
        mac_t_rx_off_cb(NULL);

        /* Send the confirm immediately. */
        gen_rx_enable_conf((buffer_t *)m, (uint8_t)MAC_SUCCESS);
        return;
    }

    /*
     * Reject the request when the MAC is currently in any of the
     * polling states or scanning.
     */
    if ((MAC_POLL_IDLE != mac_poll_state) ||
        (MAC_SCAN_IDLE != mac_scan_state)
       )
    {
        /* Send the confirm immediately. */
        gen_rx_enable_conf((buffer_t *)m, (uint8_t)MAC_TX_ACTIVE);
        return;
    }

#ifdef BEACON_SUPPORT
    if (NON_BEACON_NWK == tal_pib.BeaconOrder)
    {
        handle_rx_on(rxe->RxOnDuration, m);
    }
    else
    {
        /* We have a beacon-enabled network. */
        uint32_t curr_beacon_int_time_symbols = TAL_GET_BEACON_INTERVAL_TIME(tal_pib.BeaconOrder);
        uint32_t now_time_symbols;
        uint32_t symbols_since_beacon;
        uint32_t rx_on_time_symbols;
        retval_t timer_status;

        /*
         * Determine if (RxOnTime + RxOnDuration) is less than the beacon
         * interval.
         * According to 7.1.10.1.3:
         * On a beacon-enabled PAN, the MLME first determines whether
         * (RxOnTime + RxOnDuration) is less than the beacon interval, defined
         * by macBeaconOrder. If it is not less, the MLME issues the
         * MLME-RX-ENABLE.confirm primitive with a status of MAC_INVALID_PARAMETER.
         */

        rx_off_time_symbols = rxe->RxOnTime + rxe->RxOnDuration;

        if (rx_off_time_symbols >= curr_beacon_int_time_symbols)
        {
            /* Send the confirm immediately. */
            gen_rx_enable_conf((buffer_t *)m, (uint8_t)MAC_INVALID_PARAMETER);
            return;
        }

        pal_get_current_time(&now_time_symbols);
        now_time_symbols = TAL_CONVERT_US_TO_SYMBOLS(now_time_symbols);

        symbols_since_beacon  = tal_sub_time_symbols(now_time_symbols, tal_pib.BeaconTxTime);

        /*
         * Actually, MLME-RX-ENABLE.request in a beacon enabled PAN does
         * only make sense if the MAC is currently tracking beacons, so
         * that macBeaconTxTime is up to date. If it appears that
         * the last known macBeaconTxTime does not relate to the
         * current superframe, reject the request.
         */
        if (symbols_since_beacon > curr_beacon_int_time_symbols)
        {
            /* Send the confirm immediately. */
            gen_rx_enable_conf((buffer_t *)m, (uint8_t)MAC_INVALID_PARAMETER);
            return;
        }

        rx_on_time_symbols = tal_add_time_symbols(tal_pib.BeaconTxTime, rxe->RxOnTime);

        /* Check whether RxOnTime can still be handled in current CAP. */
        pal_get_current_time(&now_time_symbols);
        now_time_symbols = TAL_CONVERT_US_TO_SYMBOLS(now_time_symbols);

        if (tal_add_time_symbols(rx_on_time_symbols, TAL_CONVERT_US_TO_SYMBOLS(MIN_TIMEOUT))
            < now_time_symbols)
        {
            /* RxOnTime not possible within this CAP, see whether deferred
             * handling is allowed or not.. */
            if (!(rxe->DeferPermit))
            {
                gen_rx_enable_conf((buffer_t *)m, (uint8_t)MAC_PAST_TIME);
                return;
            }
            else
            {
                /*
                 * The MAC defers until the next superframe and attempts to enable
                 * the receiver in that superframe.
                 */
                rx_on_time_symbols = tal_add_time_symbols(rx_on_time_symbols,
                                                          curr_beacon_int_time_symbols);
            }
        }

        /*
         * Since the Rx-Enable timer could already be running,
         * it is stopped first, before it will be started (again).
         */
        pal_timer_stop(T_Rx_Enable);

        do
        {
            /*
             * Start a timer to turn Rx ON at the time "rxe->RxOnTime" from the start
             * of the next superframe.
             * Return value to be checked, because Rx on time could be too short
             * or in the past already.
             */
            timer_status =
                pal_timer_start(T_Rx_Enable,
                                TAL_CONVERT_SYMBOLS_TO_US(rx_on_time_symbols),
                                TIMEOUT_ABSOLUTE,
                                (FUNC_PTR())mac_t_rx_on_cb,
                                (void *)m);

            if (MAC_SUCCESS != timer_status)
            {
                rx_on_time_symbols = tal_add_time_symbols(rx_on_time_symbols,
                                                          curr_beacon_int_time_symbols);
            }
        }
        while (MAC_SUCCESS != timer_status);

        /* Remember the time to turn off the receiver. */
        rx_off_time_symbols = tal_add_time_symbols(rx_on_time_symbols, rxe->RxOnDuration);

        /* The remaining stuff will be done once the Rx On Timer expires. */
    }
#else   /* No BEACON_SUPPORT */
    handle_rx_on(rxe->RxOnDuration, m);
#endif  /* BEACON_SUPPORT / No BEACON_SUPPORT */
} /* mlme_rx_enable_request() */
/**
 * @brief Resets TAL state machine and sets the default PIB values if requested
 *
 * @param set_default_pib Defines whether PIB values need to be set
 *                        to its default values
 *
 * @return MAC_SUCCESS  if the transceiver state is changed to TRX_OFF
 *         FAILURE otherwise
 */
retval_t tal_reset(bool set_default_pib)
{
    /*
     * Do the reset stuff.
     * Set the default PIBs depending on the given parameter set_default_pib.
     * Do NOT generate random seed again.
     */
    if (internal_tal_reset(set_default_pib) != MAC_SUCCESS)
    {
        return FAILURE;
    }

#if (NUMBER_OF_TAL_TIMERS > 0)
    /* Clear all running TAL timers. */
    {
        uint8_t timer_id;

        ENTER_CRITICAL_REGION();

        for (timer_id = TAL_FIRST_TIMER_ID; timer_id <= TAL_LAST_TIMER_ID;
             timer_id++)
        {
            pal_timer_stop(timer_id);
        }

        LEAVE_CRITICAL_REGION();
    }
#endif

    /* Clear TAL Incoming Frame queue and free used buffers. */
    while (tal_incoming_frame_queue.size > 0)
    {
        buffer_t *frame = qmm_queue_remove(&tal_incoming_frame_queue, NULL);
        if (NULL != frame)
        {
            bmm_buffer_free(frame);
        }
    }

#ifdef ENABLE_TFA
    tfa_reset(set_default_pib);
#endif

    /*
     * Configure interrupt handling.
     * Install a handler for the transceiver interrupt.
     */
    pal_trx_irq_init(trx_irq_handler_cb);
    /* The pending transceiver interrupts on the microcontroller are cleared. */
    pal_trx_irq_flag_clr();
    pal_trx_irq_en();   /* Enable transceiver main interrupt. */

#ifdef ENABLE_FTN_PLL_CALIBRATION
    {
        /* Handle PLL calibration and filter tuning. */
        retval_t timer_status;

        /* Calibration timer has already been stopped within this function. */

        /* Start periodic calibration timer. */
        timer_status = pal_timer_start(TAL_CALIBRATION,
                                       TAL_CALIBRATION_TIMEOUT_US,
                                       TIMEOUT_RELATIVE,
                                       (FUNC_PTR())calibration_timer_handler_cb,
                                       NULL);

        if (timer_status != MAC_SUCCESS)
        {
            ASSERT("PLL calibration timer start problem" == 0);
        }
    }
#endif  /* ENABLE_FTN_PLL_CALIBRATION */

    return MAC_SUCCESS;
}
Exemple #13
0
/**
 * @brief Continues processing a data indication from the TAL for
 *        scanning states of the MAC (mac_scan_state == MAC_SCAN_IDLE).
 *
 * @param b_ptr Pointer to the buffer header.
 *
 * @return bool True if frame has been processed, or false otherwise.
 */
static bool process_data_ind_scanning(buffer_t *b_ptr)
{
	bool processed_in_scanning = false;

	/*
	 * We are in a scanning process now (mac_scan_state is not
	 * MAC_SCAN_IDLE),
	 * so continue with the specific scanning states.
	 */
	switch (mac_scan_state) {
#if (MAC_SCAN_ED_REQUEST_CONFIRM == 1)
	/* Energy Detect scan */
	case MAC_SCAN_ED:

		/*
		 * Ignore all frames received while performing ED measurement,
		 * or while performing CCA.
		 */
		b_ptr = b_ptr; /* Keep compiler happy. */
		break;
#endif /* (MAC_SCAN_ED_REQUEST_CONFIRM == 1) */

#if ((MAC_SCAN_PASSIVE_REQUEST_CONFIRM == 1) ||	\
		(MAC_SCAN_ACTIVE_REQUEST_CONFIRM == 1))
	/* Active scan or passive scan */
	case MAC_SCAN_ACTIVE:
	case MAC_SCAN_PASSIVE:
		if (FCF_FRAMETYPE_BEACON == mac_parse_data.frame_type) {
#if (MAC_PAN_ID_CONFLICT_AS_PC == 1)
			/* PAN-Id conflict detection as PAN-Coordinator. */
			if (MAC_PAN_COORD_STARTED == mac_state) {
				/* Node is currently scanning. */
				check_for_pan_id_conflict_as_pc(true);
			}

#endif  /* (MAC_PAN_ID_CONFLICT_AS_PC == 1) */
#if (MAC_PAN_ID_CONFLICT_NON_PC == 1)
			if (mac_pib.mac_AssociatedPANCoord &&
					((MAC_ASSOCIATED == mac_state) ||
					(MAC_COORDINATOR == mac_state))
					) {
				check_for_pan_id_conflict_non_pc(true);
			}

#endif  /* (MAC_PAN_ID_CONFLICT_NON_PC == 1) */
			mac_process_beacon_frame(b_ptr);
			processed_in_scanning = true;
		}
		break;
#endif /* ((MAC_SCAN_PASSIVE_REQUEST_CONFIRM == 1) ||
		 *(MAC_SCAN_ACTIVE_REQUEST_CONFIRM == 1)) */

#if (MAC_SCAN_ORPHAN_REQUEST_CONFIRM == 1)
	/* Orphan scan */
	case MAC_SCAN_ORPHAN:
		if (FCF_FRAMETYPE_MAC_CMD == mac_parse_data.frame_type &&
				COORDINATORREALIGNMENT ==
				mac_parse_data.mac_command) {
			/*
			 * Received coordinator realignment frame in the middle
			 * of
			 * an orphan scan.
			 */
			pal_timer_stop(T_Scan_Duration);

			mac_process_orphan_realign(b_ptr);
			processed_in_scanning = true;
		}
		break;
#endif /* (MAC_SCAN_ORPHAN_REQUEST_CONFIRM == 1) */

	default:
	{
#if (_DEBUG_ > 0)
		Assert(
				"Unexpected TAL data indication while checking mac_scan_state" ==
				0);
#endif
	}
	break;
	}

	return (processed_in_scanning);
}
Exemple #14
0
/**
 * @brief Continues processing a data indication from the TAL for
 *        non-polling and non-scanning states of the MAC
 *        (mac_poll_state == MAC_POLL_IDLE, mac_scan_state == MAC_SCAN_IDLE).
 *
 * @param b_ptr Pointer to the buffer header.
 * @param f_ptr Pointer to the frame_info_t structure.
 *
 * @return bool True if frame has been processed, or false otherwise.
 */
static bool process_data_ind_not_transient(buffer_t *b_ptr, frame_info_t *f_ptr)
{
	bool processed_in_not_transient = false;

	/*
	 * We are in MAC_POLL_IDLE and MAC_SCAN_IDLE now,
	 * so continue with the real MAC states.
	 */
	switch (mac_state) {
#if (MAC_START_REQUEST_CONFIRM == 1)
	case MAC_PAN_COORD_STARTED:
	{
		switch (mac_parse_data.frame_type) {
		case FCF_FRAMETYPE_MAC_CMD:
		{
			switch (mac_parse_data.mac_command) {
#if (MAC_ASSOCIATION_INDICATION_RESPONSE == 1)
			case ASSOCIATIONREQUEST:
				mac_process_associate_request(b_ptr);
				processed_in_not_transient = true;
				break;
#endif /* (MAC_ASSOCIATION_INDICATION_RESPONSE == 1) */

#if (MAC_DISASSOCIATION_BASIC_SUPPORT == 1)
			case DISASSOCIATIONNOTIFICATION:
				mac_process_disassociate_notification(b_ptr);
				processed_in_not_transient = true;
				break;
#endif /* (MAC_DISASSOCIATION_BASIC_SUPPORT == 1) */

#if (MAC_INDIRECT_DATA_FFD == 1)
			case DATAREQUEST:
				if (indirect_data_q.size > 0) {
					mac_process_data_request(b_ptr);
					processed_in_not_transient = true;
				} else {
					mac_handle_tx_null_data_frame();
				}
				break;
#endif /* (MAC_INDIRECT_DATA_FFD == 1) */

#if (MAC_ORPHAN_INDICATION_RESPONSE == 1)
			case ORPHANNOTIFICATION:
				mac_process_orphan_notification(b_ptr);
				processed_in_not_transient = true;
				break;
#endif /* (MAC_ORPHAN_INDICATION_RESPONSE == 1) */

			case BEACONREQUEST:
				mac_process_beacon_request(b_ptr);
				processed_in_not_transient = true;
				break;

#if (MAC_PAN_ID_CONFLICT_AS_PC == 1)
			case PANIDCONFLICTNOTIFICAION:
				mac_sync_loss(MAC_PAN_ID_CONFLICT);
				break;

#endif  /* (MAC_PAN_ID_CONFLICT_AS_PC == 1) */
#ifdef GTS_SUPPORT
			case GTSREQUEST:
				mac_process_gts_request(b_ptr);
				processed_in_not_transient = true;
#endif /* GTS_SUPPORT */

			default:
				break;
			}
		}
		break;

		case FCF_FRAMETYPE_DATA:
			mac_process_data_frame(b_ptr);
			processed_in_not_transient = true;
			break;

#if (MAC_PAN_ID_CONFLICT_AS_PC == 1)
		case FCF_FRAMETYPE_BEACON:
			/* PAN-Id conflict detection as PAN-Coordinator. */
			/* Node is not scanning. */
			check_for_pan_id_conflict_as_pc(false);
			break;
#endif  /* (MAC_PAN_ID_CONFLICT_AS_PC == 1) */

		default:
			break;
		}
	}
	break;
		/* MAC_PAN_COORD_STARTED */
#endif /* (MAC_START_REQUEST_CONFIRM == 1) */

	case MAC_IDLE:
#if (MAC_ASSOCIATION_REQUEST_CONFIRM == 1)
	case MAC_ASSOCIATED:
#endif /* (MAC_ASSOCIATION_REQUEST_CONFIRM == 1) */
#if (MAC_START_REQUEST_CONFIRM == 1)
	case MAC_COORDINATOR:
#endif /* (MAC_START_REQUEST_CONFIRM == 1) */
		{
			/* Is it a Beacon from our parent? */
			switch (mac_parse_data.frame_type) {
#if (MAC_SYNC_REQUEST == 1)
			case FCF_FRAMETYPE_BEACON:
			{
				uint32_t beacon_tx_time_symb;

				/* Check for PAN-Id conflict being NOT a PAN
				 * Corodinator. */
#if (MAC_PAN_ID_CONFLICT_NON_PC == 1)
				if (mac_pib.mac_AssociatedPANCoord &&
						(MAC_IDLE !=
						mac_state)) {
					check_for_pan_id_conflict_non_pc(false);
				}

#endif  /* (MAC_PAN_ID_CONFLICT_NON_PC == 1) */

				/* Check if the beacon is received from my
				 * parent. */
				if ((mac_parse_data.src_panid ==
						tal_pib.PANId) &&
						(((mac_parse_data.src_addr_mode
						== FCF_SHORT_ADDR) &&
						(mac_parse_data.src_addr.
						short_address ==
						mac_pib.mac_CoordShortAddress))
						||
						((mac_parse_data.src_addr_mode
						== FCF_LONG_ADDR) &&
						(mac_parse_data.src_addr.
						long_address ==
						mac_pib.mac_CoordExtendedAddress))))
				{
					beacon_tx_time_symb
						= TAL_CONVERT_US_TO_SYMBOLS(
							f_ptr->time_stamp);

#if (_DEBUG_ > 0)
					retval_t set_status =
#endif
					set_tal_pib_internal(macBeaconTxTime,
							(void *)&beacon_tx_time_symb);
#if (_DEBUG_ > 0)
					Assert(MAC_SUCCESS == set_status);
#endif
					if ((MAC_SYNC_TRACKING_BEACON ==
							mac_sync_state)
							||
							(MAC_SYNC_BEFORE_ASSOC
							==
							mac_sync_state)
							) {
						uint32_t nxt_bcn_tm;
						uint32_t beacon_int_symb;

						/* Process a received beacon. */
						mac_process_beacon_frame(b_ptr);

						/* Initialize beacon tracking
						 * timer. */
						{
							retval_t tmr_start_res
								= FAILURE;

#ifdef BEACON_SUPPORT
							if (tal_pib.BeaconOrder
									<
									NON_BEACON_NWK)
							{
								beacon_int_symb
									=
										TAL_GET_BEACON_INTERVAL_TIME(
										tal_pib.BeaconOrder);
							} else
#endif /* BEACON_SUPPORT */
							{
								beacon_int_symb
									=
										TAL_GET_BEACON_INTERVAL_TIME(
										BO_USED_FOR_MAC_PERS_TIME);
							}

							pal_timer_stop(
									T_Beacon_Tracking_Period);

#if (_DEBUG_ > 0)
							if (pal_is_timer_running(
									T_Beacon_Tracking_Period))
							{
								Assert(
										"Bcn tmr running" ==
										0);
							}

#endif

							do {
								/*
								 * Calculate the
								 * time for next
								 * beacon
								 * transmission
								 */
								beacon_tx_time_symb
									=
										tal_add_time_symbols(
										beacon_tx_time_symb,
										beacon_int_symb);

								/*
								 * Take into
								 * account the
								 * time taken by
								 * the radio to
								 * wakeup from
								 * sleep state
								 */
								nxt_bcn_tm
									=
										tal_sub_time_symbols(
										beacon_tx_time_symb,
										TAL_RADIO_WAKEUP_TIME_SYM <<
										(
											tal_pib
											.
											BeaconOrder
											+
											2));

								tmr_start_res
									=
										pal_timer_start(
										T_Beacon_Tracking_Period,
										TAL_CONVERT_SYMBOLS_TO_US(
										nxt_bcn_tm),
										TIMEOUT_ABSOLUTE,
										(
											FUNC_PTR)mac_t_tracking_beacons_cb,
										NULL);
							} while (MAC_SUCCESS !=
									tmr_start_res);
							#ifdef GTS_DEBUG
							port_pin_toggle_output_level(
									DEBUG_PIN1);
							port_pin_set_output_level(
									DEBUG_PIN2,
									0);
							#endif
						}

						/*
						 * Initialize superframe timer
						 * if required only
						 * for devices because
						 * Superframe timer is already
						 * running for
						 * coordinator.
						 */
						/* TODO */

						if (MAC_ASSOCIATED ==
								mac_state) {
							mac_superframe_state
								= MAC_ACTIVE_CAP;

							/* Check whether the
							 * radio needs to be
							 * woken up. */
							mac_trx_wakeup();

							/* Set transceiver in rx
							 * mode, otherwise it
							 * may stay in
							 * TRX_OFF). */
							tal_rx_enable(PHY_RX_ON);

							if (tal_pib.
									SuperFrameOrder
									<
									tal_pib
									.
									BeaconOrder)
							{
								pal_timer_start(
										T_Superframe,
										TAL_CONVERT_SYMBOLS_TO_US(
										TAL_GET_SUPERFRAME_DURATION_TIME(
										tal_pib
										.
										SuperFrameOrder)),
										TIMEOUT_RELATIVE,
										(
											FUNC_PTR)mac_t_start_inactive_device_cb,
										NULL);
								#ifdef GTS_DEBUG
								port_pin_set_output_level(
										DEBUG_PIN2,
										1);
								#endif
							}

#ifdef GTS_SUPPORT
							if (mac_final_cap_slot <
									FINAL_CAP_SLOT_DEFAULT)
							{
								uint32_t
										gts_tx_time
									= (
									TAL_CONVERT_SYMBOLS_TO_US(
									TAL_GET_SUPERFRAME_DURATION_TIME(
									tal_pib
									.
									SuperFrameOrder))
									>>
									4)
										* (
									mac_final_cap_slot
									+
									1);

								pal_timer_start(
										T_CAP, gts_tx_time,
										TIMEOUT_RELATIVE,
										(
											FUNC_PTR)mac_t_gts_cb,
										NULL);
							#ifdef GTS_DEBUG
								port_pin_set_output_level(
										DEBUG_PIN3,
										1);
							#endif
							}

#endif /* GTS_SUPPORT */
						}

						/* Initialize missed beacon
						 * timer. */
						mac_start_missed_beacon_timer();

						/* A device that is neither
						 * scanning nor polling shall go
						 * to sleep now. */
						if (
							(MAC_COORDINATOR !=
							mac_state)
							&&
							(MAC_SCAN_IDLE ==
							mac_scan_state)
							&&
							(MAC_POLL_IDLE ==
							mac_poll_state)
							) {
							/*
							 * If the last received
							 * beacon frame from our
							 * parent
							 * has indicated pending
							 * broadbast data, we
							 * need to
							 * stay awake, until the
							 * broadcast data has
							 * been received.
							 */
							if (!
									mac_bc_data_indicated)
							{
								/* Set radio to
								 * sleep if
								 * allowed */
								mac_sleep_trans();
							}
						}
					} else if (MAC_SYNC_ONCE ==
							mac_sync_state) {
						mac_process_beacon_frame(b_ptr);

						/* Do this after processing the
						 * beacon. */
						mac_sync_state = MAC_SYNC_NEVER;

						/* A device that is neither
						 * scanning nor polling shall go
						 * to sleep now. */
						if (
							(MAC_COORDINATOR !=
							mac_state)
							&&
							(MAC_SCAN_IDLE ==
							mac_scan_state)
							&&
							(MAC_POLL_IDLE ==
							mac_poll_state)
							) {
							/*
							 * If the last received
							 * beacon frame from our
							 * parent
							 * has indicated pending
							 * broadbast data, we
							 * need to
							 * stay awake, until the
							 * broadcast data has
							 * been received.
							 */
							if (!
									mac_bc_data_indicated)
							{
								/* Set radio to
								 * sleep if
								 * allowed */
								mac_sleep_trans();
							}
						}
					} else {
						/* Process the beacon frame */
						bmm_buffer_free(b_ptr);
					}

					processed_in_not_transient = true;
				} else {
Exemple #15
0
/**
 * @brief Implements the MLME-SYNC request.
 *
 * The MLME-SYNC.request primitive requests to synchronize with the
 * coordinator by acquiring and, if specified, tracking its beacons.
 * The MLME-SYNC.request primitive is generated by the next higher layer of a
 * device on a beacon-enabled PAN and issued to its MLME to synchronize with
 * the coordinator.
 *
 * Enable receiver and search for beacons for at most an interval of
 * [aBaseSuperframeDuration * ((2 ^ (n))+ 1)] symbols where n is the value of
 * macBeaconOrder. If a beacon frame containing the current PAN identifier of
 * the device is not received, the MLME shall repeat this search. Once the
 * number of missed beacons reaches aMaxLostBeacons, the MLME shall notify
 * the next higher layer by issuing the MLME-SYNC-LOSS.indication primitive
 * with a loss reason of BEACON_LOSS.
 *
 * @param m Pointer to the MLME sync request parameters.
 */
void mlme_sync_request(uint8_t *m)
{
#if (DEBUG > 0)
    retval_t set_status, set_status_2;
#endif

    mlme_sync_req_t *msr = (mlme_sync_req_t *)BMM_BUFFER_POINTER((buffer_t *)m);

    /*
     * Sync is only allowed for nodes that are:
     * 1) Devices (also before association.) or coordinators
     *    (no PAN coordinators),
     * 2) Currently NOT polling, and
     * 3) Currently NOT scanning.
     */
    if (
#if (MAC_START_REQUEST_CONFIRM == 1)
        (MAC_PAN_COORD_STARTED == mac_state) ||
#endif /* (MAC_START_REQUEST_CONFIRM == 1) */
        (MAC_POLL_IDLE != mac_poll_state) ||
        (MAC_SCAN_IDLE != mac_scan_state)
       )
    {
        /* Free the buffer allocated for MLME-SYNC-Request */
        bmm_buffer_free((buffer_t *)m);

        mac_sync_loss(MAC_BEACON_LOSS);

        return;
    }

    /* Stop the beacon tracking period timer. */
    pal_timer_stop(T_Beacon_Tracking_Period);

#if (DEBUG > 0)
    if (pal_is_timer_running(T_Beacon_Tracking_Period))
    {
        ASSERT("BCN tmr running" == 0);
    }
#endif

    /* Set MAC Sync state properly. */
    if (MAC_IDLE == mac_state)
    {
        /*
         * We try to sync before association.
         * This is a special sync state that checks beacon frames similar to
         * MAC_SYNC_TRACKING_BEACON while being associated.
         *
         * Before this state can be entered successfully a number of PIB
         * attributes have to be set properly:
         * 1) PAN-Id (macPANId)
         * 2) Coordinator Short or Long address (depending upon which type
         *    of addressing the coordinator is using)
         *    (macCoordShortAddress or mac macCoordExtendedAddress)
         *
         * Furthermore it is strongly recommended to set the Beacon order and
         * Superframe order (macBeaconOrder, macSuperframeOrder).
         * If these parameters are not set and the node tries to sync with a
         * network, where it never receives a beacon from, the missed beacon
         * timer (required for reporting a sync loss condition) will start
         * with a huge time value (based on a beacon order = 15).
         * If finally a beacon is received from the desired network, the timer
         * will be updated.
         * Nevertheless setting the PIB attributes before sync is safer.
         */
        mac_sync_state = MAC_SYNC_BEFORE_ASSOC;
    }
    else
    {
        if (msr->TrackBeacon)
        {
            mac_sync_state = MAC_SYNC_TRACKING_BEACON;
        }
        else
        {
            mac_sync_state = MAC_SYNC_ONCE;
        }
    }

    /* Wake up radio first */
    mac_trx_wakeup();

#if (DEBUG > 0)
    set_status =
#endif
    set_tal_pib_internal(phyCurrentPage, (void *)&(msr->ChannelPage));
#if (DEBUG > 0)
    ASSERT(MAC_SUCCESS == set_status);
#endif

#if (DEBUG > 0)
    set_status_2 =
#endif
    set_tal_pib_internal(phyCurrentChannel, (void *)&(msr->LogicalChannel));
#if (DEBUG > 0)
    ASSERT(MAC_SUCCESS == set_status_2);
#endif

    mac_start_missed_beacon_timer();

     /* Start synching by switching ON the receiver. */
    tal_rx_enable(PHY_RX_ON);

    /* Free the buffer allocated by the higher layer */
    bmm_buffer_free((buffer_t *)m);
}
Exemple #16
0
/**
 * \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. */
}
Exemple #17
0
/**
 * @brief Resets TAL state machine and sets the default PIB values if requested
 *
 * @param set_default_pib Defines whether PIB values need to be set
 *                        to its default values
 *
 * @return MAC_SUCCESS  if the transceiver state is changed to TRX_OFF
 *         FAILURE otherwise
 */
retval_t tal_reset(bool set_default_pib)
{
    /*
     * Do the reset stuff.
     * Set the default PIBs depending on the given parameter set_default_pib.
     * Do NOT generate random seed again.
     */
    if (internal_tal_reset(set_default_pib) != MAC_SUCCESS)
    {
        return FAILURE;
    }

#if (NUMBER_OF_TAL_TIMERS > 0)
    /* Clear all running TAL timers. */
    {
        uint8_t timer_id;

        ENTER_CRITICAL_REGION();

        for (timer_id = TAL_FIRST_TIMER_ID; timer_id <= TAL_LAST_TIMER_ID;
                timer_id++)
        {
            pal_timer_stop(timer_id);
        }

        LEAVE_CRITICAL_REGION();
    }
#endif

    /* Clear TAL Incoming Frame queue and free used buffers. */
    while (tal_incoming_frame_queue.size > 0)
    {
        buffer_t *frame = qmm_queue_remove(&tal_incoming_frame_queue, NULL);
        if (NULL != frame)
        {
            bmm_buffer_free(frame);
        }
    }

#ifdef ENABLE_TFA
    tfa_reset(set_default_pib);
#endif

    /*
     * Configure interrupt handling.  Clear all pending interrupts.
     * Handlers have been installed in tal_init(), and are never
     * uninstalled.
     */
    pal_trx_irq_flag_clr_rx_end();
    pal_trx_irq_flag_clr_tx_end();
#if (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP)
    pal_trx_irq_flag_clr_tstamp();
#endif /* (defined BEACON_SUPPORT) || (defined ENABLE_TSTAMP) */
    pal_trx_irq_flag_clr_awake();

    /*
     * To make sure that the CSMA seed is properly set within the transceiver,
     * put the trx to sleep briefly and wake it up again.
     */
    tal_trx_sleep(SLEEP_MODE_1);

    tal_trx_wakeup();

#ifdef ENABLE_FTN_PLL_CALIBRATION
    {
        /* Handle PLL calibration and filter tuning. */
        retval_t timer_status;

        /* Calibration timer has already been stopped within this function. */

        /* Start periodic calibration timer.*/
        timer_status = pal_timer_start(TAL_CALIBRATION,
                                       TAL_CALIBRATION_TIMEOUT_US,
                                       TIMEOUT_RELATIVE,
                                       (FUNC_PTR)calibration_timer_handler_cb,
                                       NULL);

        if (timer_status != MAC_SUCCESS)
        {
            ASSERT("PLL calibration timer start problem" == 0);
        }
    }
#endif  /* ENABLE_FTN_PLL_CALIBRATION */

#ifdef STB_ON_SAL
    stb_restart();
#endif

    return MAC_SUCCESS;
}
Exemple #18
0
/*
 * @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() */
Exemple #19
0
/**
 * \brief State machine handling slotted CSMA
 */
void slotted_csma_state_handling(void)
{
	switch (tal_csma_state) {
	case BACKOFF_WAITING_FOR_CCA_TIMER:
		break;

	case BACKOFF_WAITING_FOR_BEACON:

		/*
		 * Do not perform any operation and wait until the next beacon
		 * reception. If several beacons are not received, the beacon
		 * loss
		 * timer expires and stops the entire transaction.
		 */
		break;

	case CSMA_HANDLE_BEACON:

		/* debug pin to switch on: define ENABLE_DEBUG_PINS,
		 * pal_config.h */
		PIN_WAITING_FOR_BEACON_END();
		PIN_BEACON_LOSS_TIMER_END();

		pal_timer_stop(TAL_CSMA_BEACON_LOSS_TIMER);
		csma_backoff_calculation();
		break;

	case CSMA_ACCESS_FAILURE:
		NB++;
		BE++;
		/* ensure that BE is no more than macMaxBE */
		if (BE > tal_pib.MaxBE) {  /* macMaxBE */
			BE = tal_pib.MaxBE; /* macMaxBE */
		}

		if (NB > macMaxCSMABackoffs) {
			/* terminate with channel access failure */
			tx_done(MAC_CHANNEL_ACCESS_FAILURE);
		} else {
			/* restart backoff */
			csma_backoff_calculation();
		}

		break;

	case NO_BEACON_TRACKING:
		/* terminate with channel access failure */
		tx_done(MAC_CHANNEL_ACCESS_FAILURE);
		break;

	case FRAME_SENDING:
		/* waiting for end of frame transmission */
		break;

	case TX_DONE_SUCCESS:
		tx_done(MAC_SUCCESS);
		break;

	case TX_DONE_FRAME_PENDING:
		tx_done(TAL_FRAME_PENDING);
		break;

	case TX_DONE_NO_ACK:
		if (number_of_tx_retries < tal_pib.MaxFrameRetries) {
			number_of_tx_retries++;
			set_trx_state(CMD_RX_AACK_ON);

			/*
			 * Start the entire CSMA procedure again,
			 * but do not reset the number of transmission attempts.
			 */
			BE++;

			/* ensure that BE is no more than macMaxBE */
			if (BE > tal_pib.MaxBE) { /* macMaxBE */
				BE = tal_pib.MaxBE; /* macMaxBE */
			}

			NB = 0;
			remaining_backoff_periods
				= (uint8_t)(rand() & ((1 << BE) - 1));
			csma_backoff_calculation();
		} else {
			tx_done(MAC_NO_ACK);
		}

		PIN_NO_ACK_END();
		break;

	default:
		Assert("INVALID CSMA status" == 0);
		break;
	}
} /* csma_ca_state_handling() */
Exemple #20
0
static void tal_timers_stop(void)
{
#if (NUMBER_OF_TAL_TIMERS > 0)
#if ((MAC_SCAN_ED_REQUEST_CONFIRM == 1) && (defined BEACON_SUPPORT))
#ifdef ENABLE_FTN_PLL_CALIBRATION
    pal_timer_stop(TAL_ACK_WAIT_TIMER);
    pal_timer_stop(TAL_ED_SCAN_DURATION_TIMER);
    pal_timer_stop(TAL_ED_SAMPLE_TIMER);
    pal_timer_stop(TAL_CSMA_CCA);
    pal_timer_stop(TAL_CSMA_BEACON_LOSS_TIMER);
    pal_timer_stop(TAL_CALIBRATION);
#else
    pal_timer_stop(TAL_ACK_WAIT_TIMER);
    pal_timer_stop(TAL_ED_SCAN_DURATION_TIMER);
    pal_timer_stop(TAL_ED_SAMPLE_TIMER);
    pal_timer_stop(TAL_CSMA_CCA);
    pal_timer_stop(TAL_CSMA_BEACON_LOSS_TIMER);
#endif  /* ENABLE_FTN_PLL_CALIBRATION */
#endif

    /* ED Scan is switched on */
    /* No beacon support */
#if ((MAC_SCAN_ED_REQUEST_CONFIRM == 1) && (!defined BEACON_SUPPORT))
#ifdef ENABLE_FTN_PLL_CALIBRATION
    pal_timer_stop(TAL_ED_SCAN_DURATION_TIMER);
    pal_timer_stop(TAL_ED_SAMPLE_TIMER);
    pal_timer_stop(TAL_CALIBRATION);
#else
    pal_timer_stop(TAL_ED_SCAN_DURATION_TIMER);
    pal_timer_stop(TAL_ED_SAMPLE_TIMER);
#endif  /* ENABLE_FTN_PLL_CALIBRATION */
#endif

    /* ED Scan is switched off */
    /* Network with beacon support */
#if ((MAC_SCAN_ED_REQUEST_CONFIRM == 0) && (defined BEACON_SUPPORT))
#ifdef ENABLE_FTN_PLL_CALIBRATION
    pal_timer_stop(TAL_ACK_WAIT_TIMER);
    pal_timer_stop(TAL_CSMA_CCA);
    pal_timer_stop(TAL_CSMA_BEACON_LOSS_TIMER);
    pal_timer_stop(TAL_CALIBRATION);
#else
    pal_timer_stop(TAL_ACK_WAIT_TIMER);
    pal_timer_stop(TAL_CSMA_CCA);
    pal_timer_stop(TAL_CSMA_BEACON_LOSS_TIMER);
#endif  /* ENABLE_FTN_PLL_CALIBRATION */
#endif

    /* ED Scan is switched off */
    /* No beacon support */
#if ((MAC_SCAN_ED_REQUEST_CONFIRM == 0) && (!defined BEACON_SUPPORT))
#ifdef ENABLE_FTN_PLL_CALIBRATION
    pal_timer_stop(TAL_CALIBRATION);
#endif  /* ENABLE_FTN_PLL_CALIBRATION */
#endif
#endif /* (NUMBER_OF_TAL_TIMERS > 0) */
}