/** * @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); }
/** * @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 {