Part Number: CC2652R7
Other Parts Discussed in Thread: Z-STACK
Tool/software:
Hello,
We have encountered a race condition which results in the application task hanging during commissioning.
After startup and initialization:
zstack_bdbStartCommissioningReq_t zstack_bdbStartCommissioningReq; zstack_bdbStartCommissioningReq.commissioning_mode = BDB_COMMISSIONING_MODE_IDDLE; Zstackapi_bdbStartCommissioningReq(task_id, &zstack_bdbStartCommissioningReq); The main APP loop then receives the following events: 1. zstackmsg_CmdIDs_BDB_NOTIFICATION - mode: BDB_COMMISSIONING_INITIALIZATION - status: NO_NETWORK - remainModes: 0 APP calls bdb_StartCommissioning(BDB_COMMISSIONING_MODE_NWK_STEERING); 2. zstackmsg_CmdIDs_BDB_NOTIFICATION > - mode: NWK_STEERING > - status: IN_PROGRESS > - remainModes: 2 APP no action 3. zstackmsg_CmdIDs_DEV_STATE_CHANGE_IND - state: zstack_DevState_NWK_DISC APP no action 4. zstackmsg_CmdIDs_BDB_FILTER_NWK_DESCRIPTOR_IND APP calls Zstackapi_bdbFilterNwkDescComplete(app_task_id) 5. zstackmsg_CmdIDs_BDB_FILTER_NWK_DESCRIPTOR_IND APP calls Zstackapi_bdbFilterNwkDescComplete(app_task_id) *** App task hangs
Here's why:
The call to Zstackapi_bdbFilterNwkDescComplete in event 4 does the following:
[APP] Zstackapi_bdbFilterNwkDescComplete
[APP] => sendReqDefaultRsp
[APP] => OsalPort_msgSend
[APP] => while(!gotRsp)
[APP] {
[APP] // Wait for the response message
[APP] OsalPort_blockOnEvent(Task_self());
[APP] pCmdStatus = (zstackmsg_genericReq_t*)OsalPort_msgFindDequeue(appServiceTaskId, pMsg->hdr.event);
[APP] if(pCmdStatus)
[APP] {
[APP] gotRsp = true;
[APP] }
[APP] }
The zstack task handles the incoming message like this:
processBdbFilterNwkDescCompleteReq
[ZSTACK] => bdb_tryNwkAssoc(); joinState = BDB_JOIN_STATE_NWK_DISC
[ZSTACK] => bdb_SendMsg(task: 7, state: 3, status: fail)
[ZSTACK] => sent reponse to APP task
The BDB task takes this message and effectively does this:
bdb_event_loop
[BDB] => OsalPort_msgReceive [BDB_COMMISSIONING_STATE_JOINING]
[BDB] => bdb_ProcessOSALMsg(msg)
[BDB] => bdb_nwkDiscoveryAttempt(FALSE);
[BDB] => If secondary channel not tried yet - try
[BDB] => else
[BDB] => bdb_reportCommissioningState(BDB_COMMISSIONING_STATE_JOINING, FALSE);
[BDB] => ...
[BDB] => bdb_setFN();
[BDB] => NLME_ResetRequest();
[BDB] => ZMacReset
[BDB] => MAP_MAC_MlmeResetReq
[BDB] => OsalPort_clearTaskQueues
Perhaps you can see where this is going. In response to APP event 4, the BDB task tries the secondary channel, which leads to APP event 5.
On APP event 5, the BDB task ultimately clears all task queues. Depending on the precise timing of the various tasks, logging dis/enabled etc. this can happen before the APP task has received the response to the message sent to the zstack task.
To summarize:
1. APP calls OsalPort_msgSend (zstackmsg_CmdIDs_BDB_FILTER_NWK_DESC_COMPLETE_REQ) 2. APP blocks on itself and waits for response from the ZSTACK task - OsalPort_blockOnEvent - OsalPort_msgFindDequeue - loop 3. ZSTACK task sends msg to BDB task 4. ZSTACK task puts response in APP message queue 5. BDB task clears all message queues 6. APP waits forever for a message that will never come
Please confirm that our understanding is correct and that we are not missing something.
Best regards
Environment:
- CC2652R7
- simplelink_cc13xx_cc26xx_sdk_8_30_01_01
- TI Clang v4.0.2.LTD