This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nRF hangs when sending second UDP package using thread

Hi all,

Using the thread CLI example (on a PCA10056 board) as a starting point I would like nodes to connect automatically to a thread mesh when booting. I then want to use this mesh to exchange UDP packets.

The joining of the thread network works fine, and opening and sending a UDP package works fine the first time too.
However, when I then try to send a second package over the still opened UDP port the code hangs, it never returns from the otUdpSend method.

I can't seem to find what I'm still missing, so any help would be very welcome.

int main(int argc, char *argv[])
{
    log_init();
    scheduler_init();
    timer_init();
    leds_init();
    otError error;
    long counter = 0;

    uint32_t err_code = bsp_init(BSP_INIT_LEDS, NULL);
    APP_ERROR_CHECK(err_code);
    
    while (true)
    {
        // connect to thread mesh
        thread_instance_init();
        otLinkSetPanId(thread_ot_instance_get(), 5);
        otIp6SetEnabled(thread_ot_instance_get(), true);
        otThreadSetEnabled(thread_ot_instance_get(), true);

        const char buf[100] = "test123\0";
        otMessageInfo messageInfo;
        otUdpSocket mySocket;

        memset(&messageInfo, 0, sizeof(messageInfo));

        otIp6AddressFromString("ff03::1", &messageInfo.mPeerAddr);
        messageInfo.mPeerPort = 1994;

        error = otUdpOpen(thread_ot_instance_get(), &mySocket, HandleUdpReceive, NULL);

        otMessage *test_Message = otUdpNewMessage(thread_ot_instance_get(), NULL);
        otMessageAppend(test_Message, buf, (uint16_t)strlen(buf));

        NRF_LOG_INFO("after socket open");
     
        while (!thread_soft_reset_was_requested())
        {
            thread_process();
            app_sched_execute();

            if (NRF_LOG_PROCESS() == false)
            {
                //thread_sleep();
            }     

            otError errorUdpSend = otUdpSend(&mySocket, test_Message, &messageInfo);
            NRF_LOG_INFO(otThreadErrorToString(errorUdpSend));

        }
        NRF_LOG_INFO("SOFT RESET");
        thread_instance_finalize();
    }
}

Parents
  • It could be that you're calling otUdpSend() in essentially what is a while(true) loop. The function may not be re-entrant or may need to deal with one message at a time. I suppose with the HandleUdpReceive() callback your code will be notified when a transaction is done.

    Can you post what you have in HandleUdpReceive()?

    And if you're debugging, hitting the pause or stop on the debugger controls could help you understand where your code is stuck, with the help of "call stack" feature. IAR embedded worked for me catching a couple of issues this way. You may want to turn optimization down to Medium if set to High.

    I am on this same path to send a multicast message via UDP..

    I have tied Button 1 on nRF52830DK to sending the message, every time i push that all other nodes that have "udp open" and "upd bind :: 1994" will receive the "Hello" message. I have based this off of CLI example of nRF SDK for Thread/Zigbee 4.1.

    Let me know if you have questions.. though this is a learning curve for me too. Slight smile

    const char buf[10] = "Hello\0";
    static bool volatile button0_pushed;
    
    
    /**@brief Function for handling bsp events.
     */
    void bsp_evt_handler(bsp_event_t evt)
    {
        uint32_t err_code = 0;
        switch (evt)
        {
            case BSP_EVENT_KEY_0:
                NRF_LOG_INFO("BSP_EVENT_KEY_0!");
                button0_pushed = true;
                break;
    
            case BSP_EVENT_KEY_1:
                NRF_LOG_INFO("BSP_EVENT_KEY_1!");
                break;
    
            default:
                return; // no implementation needed
        }
        APP_ERROR_CHECK(err_code);
    }
    
    static void port_data_callback(void                * p_context,
                                   otMessage           * p_message,
                                   const otMessageInfo * p_message_info)
    {
        NRF_LOG_INFO("port_data_callback");
        NRF_LOG_INFO("ptr to msg = %08x",p_message);
    }
    
    otError send_udp_command(void)
    {
        otError error = OT_ERROR_NONE;
    
        otUdpSocket socket;
        otMessageInfo messageInfo;
    
    
        memset(&messageInfo, 0, sizeof(messageInfo));
    
        error = otUdpOpen(thread_ot_instance_get(), &socket, port_data_callback, NULL);
        if (error != OT_ERROR_NONE )
        {
            NRF_LOG_INFO("otUdpOpen err = %u", error);
            return error;
        }
        else
        {
            NRF_LOG_INFO("otUdpOpen SUCCESS!");
        }
        error = otIp6AddressFromString("FF03::1", &messageInfo.mPeerAddr);
        if (error != OT_ERROR_NONE )
        {
            NRF_LOG_INFO("otIp6AddressFromString err = %u", error);
            return error;
        }
        messageInfo.mPeerPort = (uint16_t)1994;
    
        otMessage *test_Message  = otUdpNewMessage(thread_ot_instance_get(), NULL);
    
    
    
        error = otMessageAppend(test_Message, buf, (uint16_t)strlen(buf));
        if (error != OT_ERROR_NONE )
        {
            NRF_LOG_INFO("otMessageAppend err = %u", error);
            return error;
        }
    
        error = otUdpSend(&socket, test_Message, &messageInfo);
        if(error != OT_ERROR_NONE)
        {
            NRF_LOG_ERROR("otUdpSend err = %u",error);
            NRF_LOG_INFO(otThreadErrorToString(error));
            return error;
        }
    
         if(test_Message != NULL)
        {
            //otMessageFree(test_Message);
            NRF_LOG_INFO("otMessageFree, to be added");
        }
    
    
        return error;
    }
    
    
    
    
    /***************************************************************************************************
     * @section Main
     **************************************************************************************************/
    
    int main(int argc, char *argv[])
    {
        log_init();
        scheduler_init();
        timer_init();
        leds_init();
        otError error = OT_ERROR_NONE;
    
        uint32_t err_code = bsp_init(BSP_INIT_LEDS|BSP_INIT_BUTTONS, bsp_evt_handler);
    
        APP_ERROR_CHECK(err_code);
    
        while (true)
        {
            thread_instance_init();
            error = otIp6SetEnabled(thread_ot_instance_get(), true);
            if( error ){
                NRF_LOG_ERROR("otIp6SetEnabled = %u", error);
            }
            error = otThreadSetEnabled(thread_ot_instance_get(), true);
            if( error )
            {
                NRF_LOG_ERROR("otThreadSetEnabled = %u", error);
            }
            //nrf_mem_init();
    
            while (!thread_soft_reset_was_requested())
            {
                if( button0_pushed )
                {
                    NRF_LOG_INFO("btn0");
                    send_udp_command();
                    button0_pushed = false;
                }
                thread_process();
                app_sched_execute();
    
                if (NRF_LOG_PROCESS() == false)
                {
                    thread_sleep();
                }
            }
    
            thread_instance_finalize();
        }
    }

  • Hello Everybody,

    It works perfectly for me, however the receiver node should have "udp open" and "udp bind :: 1994".

    In order to add this feature directly to main.c, so that the receiver node will get the Hello message without using CLI commands "udp open" and "udp bind :: 1994", I have defined a function receive_udp_command() and call it in main loop :

    *************************************************************************************************************************************

    *************************************************************************************************************************************

    otError receive_udp_command(void)
    {
    otError error = OT_ERROR_NONE;

    otUdpSocket * socket;
    otMessageInfo messageInfo;

    otSockAddr addr;

    memset(&addr, 0, sizeof(addr));
    memset(socket, 0, sizeof(otSockAddr));

    memset(&messageInfo, 0, sizeof(messageInfo));

    error = otUdpOpen(thread_ot_instance_get(), socket, port_data_callback, NULL);
    if (error != OT_ERROR_NONE )
    {
    NRF_LOG_INFO("otUdpOpen err = %u", error);
    return error;
    }
    if (error == OT_ERROR_NONE )
    {
    NRF_LOG_INFO("otUdpOpen SUCCESS!");
    addr.mPort = UDP_PORT ;
    error = otUdpBind(socket, &addr);
    NRF_LOG_INFO("Udp bind Success !");
    return error;
    }

    return error;
    }

    *************************************************************************************************************************************

    *************************************************************************************************************************************

    This function is called properly in main loop, unfortunately, I didn't receive Hello message after pushing the button on sender node, any help or examples ?

    Thank you so much :)

    Kind Regards,

    Houssam

  • I managed to fix this issue, I've just called otCliConsoleInputLine() function after initialization phase within main() function of the receiver node :

    int main(int argc, char *argv[])

    {

    /*Initialization*/

    log_init();
    scheduler_init();
    timer_init();
    leds_init();
    thread_instance_init();

    /*udp open*/

    char cli_cmd[] = "udp open\r\n";
    otCliConsoleInputLine(cli_cmd, strlen(cli_cmd));

    /*udp bind :: 1994*/

    char cli_cmd_2[] = "udp bind :: 1994\r\n";
    otCliConsoleInputLine(cli_cmd_2, strlen(cli_cmd_2));

    .

    .

    .

    }

    It works perfectly.

    Kind Regards,

    Houssam

Reply
  • I managed to fix this issue, I've just called otCliConsoleInputLine() function after initialization phase within main() function of the receiver node :

    int main(int argc, char *argv[])

    {

    /*Initialization*/

    log_init();
    scheduler_init();
    timer_init();
    leds_init();
    thread_instance_init();

    /*udp open*/

    char cli_cmd[] = "udp open\r\n";
    otCliConsoleInputLine(cli_cmd, strlen(cli_cmd));

    /*udp bind :: 1994*/

    char cli_cmd_2[] = "udp bind :: 1994\r\n";
    otCliConsoleInputLine(cli_cmd_2, strlen(cli_cmd_2));

    .

    .

    .

    }

    It works perfectly.

    Kind Regards,

    Houssam

Children
No Data
Related