int done = INST_NOT_DONE_YET;
#define INST_DONE_WAIT_FOR_NEXT_EVENT 1 //this signifies that the current event has been processed and instance is ready for next one #define INST_DONE_WAIT_FOR_NEXT_EVENT_TO 2 //this signifies that the current event has been processed and that instance is waiting for next one with a timeout //which will trigger if no event coming in specified time #define INST_NOT_DONE_YET 0 //this signifies that the instance is still processing the current event
int message = instance_peekevent(); //get any of the received events from ISR
int instance_peekevent(void) { int instance = 0; return instance_data[instance].dwevent[instance_data[instance].dweventPeek].type; //return the type of event that is in front of the queue }
第一次運行到這里的時候,instance_data[instance].dweventPeek 為0 ,我們在之前初始化的時候看到的結果
Peek,也就是瞟一眼,看看是否有事件,假定我們這里還米有收到任何事件。 后面我們會看事件的產生,怎么往里面裝,怎么取出。 這里只是簡單的瞟一眼。
while(done == INST_NOT_DONE_YET) { //int state = instance_data[instance].testAppState; done = instance_localdata[instance].testapprun_fn(&instance_data[instance], message) ; // run the communications application //we've processed message message = 0; }
由於進入函數的時候,我們定義了局部變量done 為INST_NOT_DONE_YET,所以至少會執行一下while 循環里面的內容。
done = instance_localdata[instance].testapprun_fn(&instance_data[instance], message) ;
回憶之前我們code分析如下內容
//應用層函數設定 void instance_setapprun(int (*apprun_fn)(instance_data_t *inst, int message)) { int instance = 0 ; instance_localdata[instance].testapprun_fn = apprun_fn; }
設定這些函數,只是提供入口,此時還不會執行。但是RX TX 回調函數是通過中斷觸發的,設定后可能會立馬執行,這個我們后續看代碼分析。
之前只是賦值,而現在才是真的執行這個函數testapprun_s
testapprun_s &instance_data[instance], message)
傳遞的兩個變量A : instance_data, 也就是我們開始初始化的變量instance
B:message. instance_peekevent()是它的返回值,我們暫且還不能假定是什么東西。
那么我們現在看看testapprun_s函數吧。
/ ------------------------------------------------------------------------------------------------------------------- // // the main instance state machine (all the instance modes Tag, Anchor or Listener use the same statemachine....) // // ------------------------------------------------------------------------------------------------------------------- // int testapprun_s(instance_data_t *inst, int message) { switch (inst->testAppState) { case TA_INIT : // printf("TA_INIT") ; switch (inst->mode) { case TAG: {
列出一段,對着就是十分糟糕的主要狀態機部分了。
在分析這段代碼前,我們需要做一些假定,暫時假定,我們現在分析流程是ANCHOR的,因為這個家伙會先啟動,由於涉及到無線通信數據收發,所以我們會時不時的切換到TAG。
到目前為止,ANCHOR 和TAG 的代碼基本都是一致的。后面狀態機就有區別了。
好了,我們假定現在設備是ANCHOR,開始狀態機第一步吧。
switch (inst->testAppState) { case TA_INIT : // printf("TA_INIT") ; switch (inst->mode) { case TAG: { …… } break; case ANCHOR: { dwt_enableframefilter(DWT_FF_NOTYPE_EN); //disable frame filtering inst->frameFilteringEnabled = 0 ; dwt_seteui(inst->eui64); dwt_setpanid(inst->panid); #if (USING_64BIT_ADDR==0) { uint16 addr = inst->eui64[0] + (inst->eui64[1] << 8); dwt_setaddress16(addr); //set source address into the message structure memcpy(&inst->msg.sourceAddr[0], inst->eui64, ADDR_BYTE_SIZE_S);
//set source address into the message structure memcpy(&inst->rng_initmsg.sourceAddr[0], inst->eui64, ADDR_BYTE_SIZE_S); } #else //set source address into the message structure memcpy(&inst->msg.sourceAddr[0], inst->eui64, ADDR_BYTE_SIZE_L); //set source address into the message structure memcpy(&inst->rng_initmsg.sourceAddr[0], inst->eui64, ADDR_BYTE_SIZE_L); #endif // First time anchor listens we don't do a delayed RX dwt_setrxaftertxdelay(0); //change to next state - wait to receive a message inst->testAppState = TA_RXE_WAIT ; dwt_setrxtimeout(0); inst->canprintinfo = 1; } break; case LISTENER: { …… } break ; // end case TA_INIT default: break; } break; // end case TA_INIT
上來case 是根據設備狀態判斷的,沒錯,我們之前初始化的時候見過這個家伙
INST_STATES testAppState ; int instance_init_s(int mode) TA_INIT
進去后,會根據不同的角色(TAG ANCHOR LISTENER)執行不同的代碼,先忽略TAG 和 LISTENER的部分,看看ANCHOR做了什么
dwt_enableframefilter(DWT_FF_NOTYPE_EN); //disable frame filtering inst->frameFilteringEnabled = 0 ;
關於幀的控制,感覺這家伙不想接收任何數據,同時對結構體frameFilteringEnabled 賦值為0.
dwt_seteui(inst->eui64); dwt_setpanid(inst->panid);
設置64位地址以及PANIND,我們在初始化的時候做的內容包括這兩個家伙了。
uint8 eui64[8]; // devices EUI 64-bit address ???? uint16 panid ; instance_init 0 xdeca // panid used in the frames
可以追進去看看這兩個函數,都是寄存器級別的操作了,我們不追了。dwt_ 開頭的都是寄存器級別的操作。
宏定義有如下一行內容
#define USING_64BIT_ADDR (1) //when set to 0 - the DecaRanging application will use 16-bit addresses
所以我們就知道執行的東西是
#else //set source address into the message structure memcpy(&inst->msg.sourceAddr[0], inst->eui64, ADDR_BYTE_SIZE_L); //set source address into the message structure memcpy(&inst->rng_initmsg.sourceAddr[0], inst->eui64, ADDR_BYTE_SIZE_L); #endif
好,關於結構體,已知參數又多了兩個msg.sourceAddr[0] 和rng_initmsg.sourceAddr[0]。 這兩個參數都是ANCHOR的長地址。(這兩個參數的值歸ANCHOR所有)
// First time anchor listens we don't do a delayed RX dwt_setrxaftertxdelay(0); //change to next state - wait to receive a message inst->testAppState = TA_RXE_WAIT ; dwt_setrxtimeout(0); inst->canprintinfo = 1;
這段代碼中有兩個dwt_ 開頭的函數,我們看注釋就可以了,取消delayed RX設定以及將rxtimeout設置為0. 修改了testAppState = TA_RXE_WAIT,同時canprintinfo 被設置為1
看到這里突然想到我們testapprun_s 傳入兩個函數,第二message 還沒有用到,確實,對ANCHOR 的TA_INIT 還沒有用到這個參數。
case TA_INIT : …… Break;
Break 了,我們需要看看 switch (inst->testAppState)之外是否還有代碼。
一直拉到testapprun_s最后,發現只有這個了
return inst->done; } // end testapprun()
好吧,我們剛才沒有看inst->done是個什么東西,返回去再看看
仔細在TA_INITàANCHOR 代碼塊找了一圈發現並沒有設置這個inst->done. 好吧,那我們看看之前初始化的時候是否有設置。
int done ; //done with the current event/wait for next event to arrive
沒有標記,那可能是沒有設置,我們那認為它返回的初始值0. 先這樣吧,第一次嘗試了testapprun_s,我們趕快跳到instance_run(void) 中吧。
while(done == INST_NOT_DONE_YET) { //int state = instance_data[instance].testAppState; done = instance_localdata[instance].testapprun_fn(&instance_data[instance], message) ; // run the communications application //we've processed message message = 0; }
我們假定done為0,name看看是否還在while中
#define INST_NOT_DONE_YET 0
看來很不幸,滿足while 條件,再次執行,再次進入到testapprun_s中。