• 【DWM1000】 code 解密3一ANCHOR RUN起来


    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中。

    博客讨论一些室内定位(DWM1000/CC2431/CC2530) 以及一些随性的技术。博文可以转载,但需要注明出处!
  • 相关阅读:

    修改 linux 时区时间和 php 时区
    夺命雷公狗—玩转SEO---21---域名购买技巧
    夺命雷公狗—玩转SEO---20---K站
    夺命雷公狗—玩转SEO---19---降权
    夺命雷公狗—玩转SEO---18---索引
    夺命雷公狗—玩转SEO---17---收录
    夺命雷公狗—玩转SEO---16---关键词词性和定位关键词
    夺命雷公狗—玩转SEO---15---域名
    夺命雷公狗—玩转SEO---14---空间和服务器的区别
  • 原文地址:https://www.cnblogs.com/tuzhuke/p/7706901.html
Copyright © 2020-2023  润新知