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

zgp_init_by_scheduler not call at first startup of my device

Hello,

I have a project of a device with 2 endpoint plus the GP endpoint (242). It's a coordinator.

at first startup, the green power endpoint doesn't appear in the response of a node descriptor request.

if I reboot my device, the GP endpoint appear in the response of the node descriptor request.

I have found that during the first boot, the zgp_init_by_scheduler  function, from libgppb.a is not call.

Is someone have some information about what is wrong in my device please ?

Best regards,

Jean-Philippe

Parents
  • Hello,
    I check with the CLI example, which doesn't have the problem.
    So, I think the problem is only in my project.

    PanId is 951B

    Nwk Key : F8 7B 44 41 6E D7 A1 D8 C1 B4 3E 29 E4 F2 DC 59
    My device is the coordinator : 0000 F4CE36F5E6C170DA

    capture no GP endpoint at first startup.pcapng

  • This project was before with SDK v4.1.0 and the behaviour is not present with this version, it appear with the v4.2.0

    Best regard

  • Hi,

    Yes, my device is a GP Combo Basic device. And it's not an End device. It can be a ZC or a ZR, depending on event comes after the start.

    I have done the test with zb_set_network_coordinator_role or zb_set_network_router_role before zboss_start_no_autostart, and yes, with that, the endpoint appear after the first startup, without restart the device.

  • An other workaround I think to not modified my existing device:
    call zgp_init_by_scheduler in the signal handler 'zboss_signal_handler', at ZB_ZDO_SIGNAL_SKIP_STARTUP signal.

    Is it a more acceptable workaround ?

    I see that in the function 'zgp_init_by_scheduler', a booleen indicate if the initialisation is ever made or not.
    So, at first startup 'my call' is execute, and for next startup, the 'stack call' is execute.

    Best regard

  • Hi Jean-Philippe,

    Thank you for verifying. It is very helpful to know that this issue does not happen when the role is set before the stack is started.

    It is still not a good idea to start the stack before setting the device role. One possible solution I can think of is to do something similar to how Sleepy End Device (SED) behavior is set up in the light switch example. There, holding a specific button while resetting the board enables SED. This is implemented by sleepy_device_setup() being called in main() before the stack starts, which checks the state of the button and sets SED accordingly:

    static void sleepy_device_setup(void)
    {
        zb_set_rx_on_when_idle(bsp_button_is_pressed(SLEEPY_ON_BUTTON) ? ZB_FALSE : ZB_TRUE);
     ...
    }

    Since you are using button presses to select the role, would it be possible to do something similar on your device?

    Best regards,

    Marte

  • Hello,

    I am not understand well the SED example and what do the button.

    what did you call 'before start stack' ?
    This is the call of 'zboss_main_loop_iteration' or 'zboss_start_no_autostart' ?

    Thanks

  • Hi Jean-Philippe,

    This is before both zboss_start_no_autostart() and zboss_main_loop_iteration().

    In the SED/light switch example button 3 is set as SLEEPY_ON_BUTTON. It is implemented in such a way that if you press button 3 while resetting or turning on the board, then SED behavior will be enabled. This is done by checking if the button is pressed before zboss_start_no_autostart() is called.

    So in your case something similar might be to either have one of the roles as default (e.g router), and holding in the button while resetting/powering on the board will set the other role instead (e.g. coordinator). Or you can use two different buttons and set the role depending on which button is pressed. A simple implementation of the first could be something like this:

    /* Note: BSP_BOARD_BUTTON_2 is button 3 on DK*/
    #define DEVICE_ROLE_BUTTON         BSP_BOARD_BUTTON_2 /**< Button ID used to determine device role (pressed means coordinator). */
    
    
    /**@brief Function to set the device role according to DEVICE_ROLE_BUTTON state.
    */
    static void device_role_setup(void)
    {
        if (bsp_button_is_pressed(DEVICE_ROLE_BUTTON))
        {
            /* Coordinator role */
            /* Set channels on which the coordinator will try to create a new network. */
            zb_set_network_coordinator_role(IEEE_CHANNEL_MASK);
            // Add if you have any other coordinator specific things to set on start-up
        }
        else
        {
            /* Router role */
            /* Set static long IEEE address. */
            zb_set_network_router_role(IEEE_CHANNEL_MASK);
            zb_set_keepalive_timeout(ZB_MILLISECONDS_TO_BEACON_INTERVAL(3000));
            // Add if you have any other router specific things to set on start-up
        }
    }
    
    
    
    /**@brief Function for application main entry.
     */
    int main(void)
    {
        zb_ret_t       zb_err_code;
        zb_ieee_addr_t ieee_addr;
    
        /* Initialize timers, loging system and GPIOs. */
        timers_init();
        log_init();
        leds_buttons_init();
    
        /* Initialize Zigbee stack. */
        ZB_INIT("my_device");
    
        /* Set device address to the value read from FICR registers. */
        zb_osif_get_ieee_eui64(ieee_addr);
        zb_set_long_address(ieee_addr);
    
        device_role_setup();
        zb_set_max_children(MAX_CHILDREN);
        zigbee_erase_persistent_storage(ERASE_PERSISTENT_CONFIG);
    
    
        ...
    
    
        /** Start Zigbee Stack. */
        zb_err_code = zboss_start_no_autostart();
        ZB_ERROR_CHECK(zb_err_code);
    
        while(1)
        {
            zboss_main_loop_iteration();
            UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
        }
    }

    Note: this is a simplified version of main(). You might have to add more to the router role configuration, and/or have a global variable to keep track of the role if you want to do things only if it is a specific role.

    Hope this clears up what I was trying to say earlier.

    Best regards,

    Marte

Reply
  • Hi Jean-Philippe,

    This is before both zboss_start_no_autostart() and zboss_main_loop_iteration().

    In the SED/light switch example button 3 is set as SLEEPY_ON_BUTTON. It is implemented in such a way that if you press button 3 while resetting or turning on the board, then SED behavior will be enabled. This is done by checking if the button is pressed before zboss_start_no_autostart() is called.

    So in your case something similar might be to either have one of the roles as default (e.g router), and holding in the button while resetting/powering on the board will set the other role instead (e.g. coordinator). Or you can use two different buttons and set the role depending on which button is pressed. A simple implementation of the first could be something like this:

    /* Note: BSP_BOARD_BUTTON_2 is button 3 on DK*/
    #define DEVICE_ROLE_BUTTON         BSP_BOARD_BUTTON_2 /**< Button ID used to determine device role (pressed means coordinator). */
    
    
    /**@brief Function to set the device role according to DEVICE_ROLE_BUTTON state.
    */
    static void device_role_setup(void)
    {
        if (bsp_button_is_pressed(DEVICE_ROLE_BUTTON))
        {
            /* Coordinator role */
            /* Set channels on which the coordinator will try to create a new network. */
            zb_set_network_coordinator_role(IEEE_CHANNEL_MASK);
            // Add if you have any other coordinator specific things to set on start-up
        }
        else
        {
            /* Router role */
            /* Set static long IEEE address. */
            zb_set_network_router_role(IEEE_CHANNEL_MASK);
            zb_set_keepalive_timeout(ZB_MILLISECONDS_TO_BEACON_INTERVAL(3000));
            // Add if you have any other router specific things to set on start-up
        }
    }
    
    
    
    /**@brief Function for application main entry.
     */
    int main(void)
    {
        zb_ret_t       zb_err_code;
        zb_ieee_addr_t ieee_addr;
    
        /* Initialize timers, loging system and GPIOs. */
        timers_init();
        log_init();
        leds_buttons_init();
    
        /* Initialize Zigbee stack. */
        ZB_INIT("my_device");
    
        /* Set device address to the value read from FICR registers. */
        zb_osif_get_ieee_eui64(ieee_addr);
        zb_set_long_address(ieee_addr);
    
        device_role_setup();
        zb_set_max_children(MAX_CHILDREN);
        zigbee_erase_persistent_storage(ERASE_PERSISTENT_CONFIG);
    
    
        ...
    
    
        /** Start Zigbee Stack. */
        zb_err_code = zboss_start_no_autostart();
        ZB_ERROR_CHECK(zb_err_code);
    
        while(1)
        {
            zboss_main_loop_iteration();
            UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
        }
    }

    Note: this is a simplified version of main(). You might have to add more to the router role configuration, and/or have a global variable to keep track of the role if you want to do things only if it is a specific role.

    Hope this clears up what I was trying to say earlier.

    Best regards,

    Marte

Children
No Data
Related