Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs

As coordinator, mlme_associate_resp from 802, MAC-lib, gives ASSERTION FAILED

Hello,

I am using the 802_15_4 MAC api to configure my device as a coordinator.

After it has been configured as a coordinator I want another device to connect to it.

I can see by sniffing the channel that an association request is sent from the device and I can see that an association_indication on the coordinator is received.

When I then try to send an association response with 

void mlme_associate_resp(mlme_associate_resp_t * resp);

I get an assert fault from the precompiled library:

00> <info> app: Assertion info: fsm:20004dc4,s:0,e:9
00> 
00> <error> app: Assertion fault: !(p_fsm->recursion_protection == 0) line: 310 file: sys_fsm.c 
00> 
00> <error> app: ASSERTION FAILED at sys_fsm.c:310

Further more, the association_response is not sent and the radio stack freezes, i.e. no mlme function calls will trigger a callback.

Anyone have a clue what the assert fault is from?

I am using the structure defined in the library and I have tried both static declaration and using malloc to keep the structure in memory long enough.

Sniffer trace:

associate_indication function:

void panEnterAssociateInd(mlme_associate_ind_t *association_indication)
{
    ShortAddress           shortaddr;
    Capability             capability;
    mlme_associate_resp_t *associate_response;
    Boolean                adlIsUpToDate; // Associated Device List is up to date.
    Boolean                pairingIsActive;
    Boolean                isOk;


    shortaddr  = UD_ADDR_NOT_ASSIGNED;
    capability = association_indication->capability_information;

    // Allocate a reponse message.                                       .
    associate_response = (mlme_associate_resp_t*)malloc(sizeof(mlme_associate_resp_t));
    IC_ERROR_ASSERT( associate_response != NULL );

    // Fill in reponse message for association denied case.
    (void)memcpy(&associate_response->device_address, &association_indication->device_address, sizeof(mac_addr_t));

    associate_response->assoc_short_address = shortaddr;
    associate_response->status = MAC_PAN_ACCESS_DENIED;

    // Free input message.

    if ( ( capability & (1 << ALLOCATE_ADDRESS_BIT) ) == 0 )
    {
        // Device cannot handle short addresses. Association denied.
        mlme_associate_resp(associate_response);
        return;
    }

    adlIsUpToDate = FALSE;
    if (asDevIsMemberMac((uint8_t*)&associate_response->device_address))
    {
        /* shortaddr = asDevGetShortAddress( resp->msgData.associateRes.deviceAddress ); */
        shortaddr = asDevGetShortAddress((uint8_t*)&associate_response->device_address);
        if ( asDevGetCapability( shortaddr ) == capability )
        {
            // Client is already in ADL with correct capability.
            adlIsUpToDate = TRUE;
        }
        else
        {
            // Client is in ADL, but with wrong capability. Remove to allow new allocation.
            asDevRemove( shortaddr );
        }
    }

    if ( !adlIsUpToDate )
    {
        if ( isTemporary( capability ) )
        {
            if ( !asDevHasFreeSlot( TRUE ) )
            {
                // Make room for a new temporary association by cleaning old entries.
                asDevRemoveTemporary();
            }
        }
        else
        {
            // Permanent
            if ( !asDevHasFreeSlot( FALSE ) )
            {
                // List is full. Association denied.
                mlme_associate_resp(associate_response);
                return;
            }
        }

        // Create a new address and add to ADL.
        shortaddr       = asDevGetNextFreeShortAddress();
        pairingIsActive = ( beaconPayload.protVerAndPairing & UD_BEACON_PAIRING_MASK ) != 0;
        isOk = asDevAdd( shortaddr,
                         (uint8_t*)&associate_response->device_address,
                         capability,
                         pairingIsActive,
                         TRUE );
        if ( !isOk )
        {
            // Failed to insert in ADL. Pairing mode mismatch? Association denied.
            mlme_associate_resp(associate_response);
            return;
        }
    }

    // Association is granted.
    associate_response->assoc_short_address = shortaddr;
    associate_response->status = MAC_ASSOCIATION_SUCCESSFUL;

    mlme_associate_resp(associate_response);
    urReportEvent( RADIO_EV_PAIRED, shortaddr, uhfpGetShortAddr() );
}

  • Hi

    I will look into this case tomorrow

    Regards,
    Sigurd Hellesvik

  • If you need any more information, just let me know

    Regards

    Linus

  • I set:

    MAC_BEACON_PAYLOAD_LENGTH

    MAC_BEACON_PAYLOAD

    MAC_MAX_CSMA_BACKOFFS 

    MAC_TRANSACTION_PERSISTENCE_TIME
    MAC_SHORT_ADDRESS
    MAC_ASSOCIATION_PERMIT = True

    And then my start request looks as follows:

    //My PanId
    start_request->pan_id = myPanId;
    // logical channel
    start_request->logical_channel = logical_channel;
    // Beacon Order - 0xF = turn off beacons
    start_request->beacon_order = 0x07;
    // Superframe Order - 0xF = turn off beacons
    start_request->superframe_order = 0x05;
    // Be a PAN coordinator
    start_request->pan_coordinator = TRUE;
    // Don't use battery life extension
    start_request->battery_life_extension = FALSE;
    // True if this is a realignment
    start_request->coord_realignment = TRUE;

    Is there something I am missing to set in MAC PIB?

    BR

    Linus

  • Hi,

    We see that you call mlme_associate_resp() function directly from panEnterAssociateInd() handler, we think calling mlme_associate_resp() from IRQ context might be the cause of the error message.

    Can you try to pass execution context to the thread and then call mlme_associate_resp() from the thread instead?

    Best regards,
    Kenneth

  • Hi,

    Thank you for your response.

    I moved all code from panEnterAssociatedInd() to another function, leaving only a flag and a memcpy().

    The code was moved to another function which is called from main loop when flag is set.

    static U8  association_granted = false;
    static mlme_associate_ind_t latest_association_ind;
    
    void panEnterAssociateInd(mlme_associate_ind_t *association_indication)
    {
    
        (void)memcpy(&latest_association_ind.capability_information, &association_indication->capability_information, sizeof(uint8_t));
        (void)memcpy(&latest_association_ind.device_address, &association_indication->device_address, sizeof(uint64_t));
        
        association_granted = true;
    }
    
    
    void sendAssociateResp( void )
    {
    
        ShortAddress           shortaddr;
        Capability             capability;
        mlme_associate_resp_t *associate_response;
        Boolean                adlIsUpToDate; // Associated Device List is up to date.
        Boolean                pairingIsActive;
        Boolean                isOk;
    
        //NRF_LOG_INFO("3. Capability: 0x%x, dev_addr: 0x%x", (uint8_t)latest_association_ind.capability_information,(uint64_t)latest_association_ind.device_address );
    
        shortaddr  = UD_ADDR_NOT_ASSIGNED;
        capability = latest_association_ind.capability_information;
    
        // Allocate a reponse message.                                       .
        associate_response = (mlme_associate_resp_t*)malloc(sizeof(mlme_associate_resp_t));
        IC_ERROR_ASSERT( associate_response != NULL );
    
        // Fill in reponse message for association denied case.
        (void)memcpy(&associate_response->device_address, &latest_association_ind.device_address, sizeof(mac_addr_t));
    
        associate_response->assoc_short_address = shortaddr;
        associate_response->status = MAC_PAN_ACCESS_DENIED;
    
        // Free input message.
    
        if ( ( capability & (1 << ALLOCATE_ADDRESS_BIT) ) == 0 )
        {
            // Device cannot handle short addresses. Association denied.
            mlme_associate_resp(associate_response);
            association_granted = false;
            return;
        }
    
        adlIsUpToDate = FALSE;
        if (asDevIsMemberMac((uint8_t*)&associate_response->device_address))
        {
            /* shortaddr = asDevGetShortAddress( resp->msgData.associateRes.deviceAddress ); */
            shortaddr = asDevGetShortAddress((uint8_t*)&associate_response->device_address);
            if ( asDevGetCapability( shortaddr ) == capability )
            {
                // Client is already in ADL with correct capability.
                adlIsUpToDate = TRUE;
            }
            else
            {
                // Client is in ADL, but with wrong capability. Remove to allow new allocation.
                asDevRemove( shortaddr );
            }
        }
    
        if ( !adlIsUpToDate )
        {
            if ( isTemporary( capability ) )
            {
                if ( !asDevHasFreeSlot( TRUE ) )
                {
                    // Make room for a new temporary association by cleaning old entries.
                    asDevRemoveTemporary();
                }
            }
            else
            {
                // Permanent
                if ( !asDevHasFreeSlot( FALSE ) )
                {
                    // List is full. Association denied.
                    mlme_associate_resp(associate_response);
                    association_granted = false;
                    return;
                }
            }
    
            // Create a new address and add to ADL.
            shortaddr       = asDevGetNextFreeShortAddress();
            pairingIsActive = ( beaconPayload.protVerAndPairing & UD_BEACON_PAIRING_MASK ) != 0;
            isOk = asDevAdd( shortaddr,
                             (uint8_t*)&associate_response->device_address,
                             capability,
                             pairingIsActive,
                             TRUE );
            if ( !isOk )
            {
                // Failed to insert in ADL. Pairing mode mismatch? Association denied.
                mlme_associate_resp(associate_response);
                association_granted = false;
                return;
            }
        }
    
        // Association is granted.
        associate_response->assoc_short_address = shortaddr;
        associate_response->status = MAC_ASSOCIATION_SUCCESSFUL;
        mlme_associate_resp(associate_response);
        urReportEvent( RADIO_EV_PAIRED, shortaddr, uhfpGetShortAddr() );
        association_granted = false;
        NRF_LOG_INFO("Sent associate response");
    }

    I no longer get the assertion fault which is great!

    However the sniffer-trace still looks the same (no associate response actually sent) and the radio stack freeze still occurs.

    I did not receive any other error messages either.

    Any idea what could be stopping it from sending a response?

    BR

    Linus 

Related