示例#1
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);
    }
}
示例#2
0
/*
 * @brief Timer function after sync request to count missed beacon frames.
 *
 * This function is a callback from the missed beacon timer and implements the
 * generation of sync loss if required.
 *
 * @param callback_parameter Callback parameter of the expired missed beacon
 *                           tracking timer
 */
static void mac_t_missed_beacons_cb(void *callback_parameter)
{
    if (MAC_SYNC_NEVER != mac_sync_state)
    {
        /* Since the node lost sync with it's parent, it reports sync loss. */
        mac_sync_loss(MAC_BEACON_LOSS);
    }


    callback_parameter = callback_parameter;  /* Keep compiler happy. */
}
示例#3
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);
}
示例#4
0
/**
 * @brief Processing a coordinator realignment command frame
 *
 * This function processes a coordinator realignment command frame received
 * from the coordinator (while NOT being in the middle of an Orphan scan, but
 * rather after initiation of a start request primitive from the coordinator
 * indicating realingment.
 * The PAN ID, coord. short address, logical channel, and the device's new
 * short address will be written to the PIB.
 *
 * @param ind Frame reception buffer
 */
void mac_process_coord_realign(buffer_t *ind)
{
    /*
     * The coordinator realignment command is received without the orphan
     * notification. Hence a sync loss indication is given to NHLE.
     */
    mac_sync_loss(MAC_REALIGNMENT);

    /*
     * The buffer in which the coordinator realignment is received is
     * freed up
     */
    bmm_buffer_free((buffer_t *)ind);

    /* Set the appropriate PIB entries */

#if (DEBUG > 0)
    retval_t set_status =
#endif
    set_tal_pib_internal(macPANId,
        (void *)&mac_parse_data.mac_payload_data.coord_realign_data.pan_id);

#if (DEBUG > 0)
    ASSERT(MAC_SUCCESS == set_status);
#endif

    if (BROADCAST != mac_parse_data.mac_payload_data.coord_realign_data.short_addr)
    {
        /* Short address only to be set if not broadcast address */
#if (DEBUG > 0)
        set_status =
#endif
        set_tal_pib_internal(macShortAddress,
            (void *)&mac_parse_data.mac_payload_data.coord_realign_data.short_addr);

#if (DEBUG > 0)
        ASSERT(MAC_SUCCESS == set_status);
#endif
    }

    mac_pib.mac_CoordShortAddress =
            mac_parse_data.mac_payload_data.coord_realign_data.coord_short_addr;

    /*
     * If frame version subfield indicates a 802.15.4-2006 compatible frame,
     * the channel page is appended as additional information element.
     */
    if (mac_parse_data.fcf & FCF_FRAME_VERSION_2006)
    {
#if (DEBUG > 0)
        set_status =
#endif
        set_tal_pib_internal(phyCurrentPage,
                             (void *)&mac_parse_data.mac_payload_data.coord_realign_data.channel_page);
#if (DEBUG > 0)
        ASSERT(MAC_SUCCESS == set_status);
#endif
    }

#if (DEBUG > 0)
    set_status =
#endif
    set_tal_pib_internal(phyCurrentChannel,
                         (void *)&mac_parse_data.mac_payload_data.coord_realign_data.logical_channel);

#if (DEBUG > 0)
    ASSERT(MAC_SUCCESS == set_status);
#endif
} /* mac_process_coord_realign() */
示例#5
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 {