Crash/reboot when calling wiced_dct_read_lock()

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
SeFe_4295646
Level 3
Level 3
First like received First like given

I've created a project, copied the config_join_ping example used on the CYW943907AEVAL1F board.  In my copy I create a 2nd thread to do some other work, and created two new console commands to allow me to monitor / test my worker thread.

My worker thread is small, currently it has 2 jobs - 1 send a command via a different UART to another processor, get a response; after the response I need to make a decision based on the state of our WiFi provisioning.  However if I call wiced_dct_read_lock( (void**) &dct_wifi_config, WICED_FALSE, DCT_WIFI_CONFIG_SECTION, 0, sizeof( *dct_wifi_config ) ) from my worker thread, the device resets.

If I call the same from the console thread, (in a test command function I added), it works fine, but seems it cannot be called from a different thread.

There is a delay at the start of my worker thread, to allow the console to finish printing and ensure nothing else should be going on at the same time, although from my reading wiced_dct_read_lock should be thread safe.

Anyone have any idea why / what I'm doing wrong?

I've been unable to run the debugger because in a debug build I don't get this far - separate question on that subject already posted.

0 Likes
1 Solution

Hello,

The pointer to variable that receives the thread handle (wiced_thread_t worker; ) is a local variable in the code attached in previous response. Kindly make it a global variable to solve the reset issue.

View solution in original post

13 Replies
KotnaniK_71
Employee
Employee
50 likes received 25 likes received 10 likes received

Hi,

Can you please try to debug using Free RTOS or share your simplified code details.

Thanks.

0 Likes
SeFe_4295646
Level 3
Level 3
First like received First like given

If using FreeRTOS (tried yesterday as a result of a debug problem with ThreadX) the function works fine, no errors / reboot.

Happy to share source - can I PM rather than publish?

Yes. please share me the code in PM.

Thanks.

0 Likes

Hi,

Can you please provide an update on this issue.

Thanks.

0 Likes
lock attach
Attachments are accessible only for community members.

Ok, we've made a lot of progress since then, but still have a problem

calling wiced_dct_read_lock() OR wiced_dct_read_with_copy() when using

ThreadX.

We've tried 2 different ways, both in our is_wifi_provisioned()

function, currently using the latter as it does not need a malloc/free

and I think thats more efficient.  Either method crashes and reboots

with no exception/dump in ThreadX, but work normally in FreeRTOS.

This only happens if called from our wifi_manager() thread, not if

called from the console thread.

You had earlier sent me an e-mail regarding the scan command - I

haven't been attempting a scan, so I don't know if that works or not at

this time.

The code flow is essentially the same through the code

today.  Disabling the sicom_listener() thread is mostly irrelevant

(except that thread prevents me from running debug mode in ThreadX -

but I'm not too worried about running the debugger at the moment).

Anyway, latest .c file attached.

You can disable the sicom_listener (SiLabs reader) thread commenting

line 928.Crash happens at line 440 when is_wifi_provisioned() is called

from wifi_manager() in line 510.  If you comment line 510 (replace with

"if (0) {" you can avoid the crash in ThreadX and call the same

function from the command line using my "isprov" command - see line 741

- which works in both RTOSs.

We can continue with FreeRTOS for now, but I see advantages of using

ThreadX (especially if that's largely in ROM saving us flash space) -

but I cannot figure out why I can't call is_wifi_provisioned() ->

wiced_dct_read_with_copy() from my Wifi Manager thread in ThreadX.

Best regards

lock attach
Attachments are accessible only for community members.

Hi,

Sorry for the delay in getting back to this.

By using your code and above instructions, I'm able to build, debug the code and go through the Wifi_manager thread as shown in attached screenshot.

In my previous response regarding scan command, I observed that there is memory leak happened in the call back function scan_result_handler because you haven't freed the memory for malloced_scan_result.

Kindly try the attached code and let me know is there any specific command to reproduce the issue if crash happens.

Thanks.

SeFe_4295646
Level 3
Level 3
First like received First like given

Thanks for the feedback - however I did not get your attachments here or via e-mail.

Also - no command is required to get to the crash - however, since you do not have our other processor connected - you'll need to comment lines 418 though and including 422 or the wifi manager thread will hang there.

I do have not been using the scan command - and the scan_result_hanlder is straight from your example app - so the memory leak (which I'd be happy to fix if I don't just remove the scan command) is in the example code.

Happy to look at & test your fix.  But please see if you get the reset described after commenting / removing the above lines.

Thanks.

0 Likes
lock attach
Attachments are accessible only for community members.

Hi,

I have tried commenting the lines 418 to 422 in the attached code but unable to get the reset and reproduce the same. Again, I have attached the code for your reference in this response. Kindly confirm if it's the same code which you've used in the earlier. If it's not the same code, please share me the updated version of the code or let me know the changes which you did in the functions/threads instead of line numbers.

If you are still unable to access the attachments, please do let me know such that I will send them to you personally.

Thanks.

SeFe_4295646
Level 3
Level 3
First like received First like given

Ya still no attachments - please send direct.  Thanks.

0 Likes

I have sent the attachments personally. Kindly check and let me know if the crash happens.

Also, please go through the full conversation in Cypress Developer community Crash/reboot when calling wiced_dct_read_lock()  where you can find the attachments.

Thanks.

SeFe_4295646
Level 3
Level 3
First like received First like given

Ok - this had gotten left on the back burner for a bit - we were able to continue development with FreeRTOS until now.

We are ready to implement over the air updates (OTA2) which according to documentation requires ThreadX, so this is now a priority for Notion.

I have recreated the problem with a vastly simplified source I can share here openly.  I started with the config_join_ping example from the CY943907AEVAL1F_KitPackage.zip file provided for our dev kit.

I create and start a worker thread that attempts to read the device_configured value from the DTC with a call to wiced_dct_read_with_copy()

If built for ThreadX - it crashes and restarts when that function is called (5 seconds from thread start).  If built for FreeRTOS, it works correctly, the function returning the correct value when called (every 5 seconds starting 5 seconds from start).

I can prove it is that function call by commenting out that call only (line 121 in the code below) search for the comment "comment this the next line and this function code works with ThreadX"

Note that this code still has the memory bug in scan as is in the .zip file.  NO COMMANDS ARE REQUIRED TO OBSERVE THE ISSUE, with ThreadX the code simply restarts every 5 seconds, with FreeRTOS you get the line "waiting" every 5 seconds (you can send the config command to change the result any time, but no command is required to see the crash).

********** Code follows **********

/*

* Copyright 2017, Cypress Semiconductor Corporation or a subsidiary oF

* Cypress Semiconductor Corporation. All Rights Reserved.

*

* This software, associated documentation and materials ("Software"),

* is owned by Cypress Semiconductor Corporation

* or one of its subsidiaries ("Cypress") and is protected by and subject to

* worldwide patent protection (United States and foreign),

* United States copyright laws and international treaty provisions.

* Therefore, you may use this Software only as provided in the license

* agreement accompanying the software package from which you

* obtained this Software ("EULA").

* If no EULA applies, Cypress hereby grants you a personal, non-exclusive,

* non-transferable license to copy, modify, and compile the Software

* source code solely for use in connection with Cypress's

* integrated circuit products. Any reproduction, modification, translation,

* compilation, or representation of this Software except as specified

* above is prohibited without the express written permission of Cypress.

*

* Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO WARRANTY OF ANY KIND,

* EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED

* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress

* reserves the right to make changes to the Software without notice. Cypress

* does not assume any liability arising out of the application or use of the

* Software or any product or circuit described in the Software. Cypress does

* not authorize its products for use in any products where a malfunction or

* failure of the Cypress product may reasonably be expected to result in

* significant property damage, injury or death ("High Risk Product"). By

* including Cypress's product in a High Risk Product, the manufacturer

* of such system or application assumes all risk of such use and in doing

* so agrees to indemnify Cypress against all liability.

*/

/** @file

*

* A simple application that scans, stores AP & pass phrase in DCT, joins an AP based on configuration in Device Configuration Table (DCT).

* config <STA name and pass key>

*       - adds AP settings to DCT

*   join

*       - Joins station set in DCT

*   print_config

*       - prints current wifi configuration

*   scan

*       - prints current wifi configuration

*   ping <ip address>

*       - pings wifi configuration

*   disconnect

*       - disconnects from Access Point (AP)

*/

#include "wiced.h"

#include "command_console.h"

#include "wiced_management.h"

#include "command_console_ping.h"

/******************************************************

*                      Macros

******************************************************/

/******************************************************

*                    Constants

******************************************************/

#define MAX_LINE_LENGTH  (128)

#define MAX_HISTORY_LENGTH (20)

#define MAX_NUM_COMMAND_TABLE  (8)

static char line_buffer[MAX_LINE_LENGTH];

static char history_buffer_storage[MAX_LINE_LENGTH * MAX_HISTORY_LENGTH];

/******************************************************

*                   Enumerations

******************************************************/

/******************************************************

*                 Type Definitions

******************************************************/

/******************************************************

*                    Structures

******************************************************/

/******************************************************

*               Static Function Declarations

******************************************************/

static wiced_result_t print_wifi_config_dct ( void );

wiced_result_t scan_result_handler( wiced_scan_handler_result_t* malloced_scan_result );

/******************************************************

*               Variable Definitions

******************************************************/

typedef struct

{

    wiced_semaphore_t   semaphore;      /* Semaphore used for signaling scan complete */

    uint32_t            result_count;   /* Count to measure the total scan results    */

} app_scan_data_t;

#define DIAGNOSTICS_COMMANDS \

{ "config",  wifi_config,  1, NULL, NULL, "<STA name and pass key>", "adds AP settings to DCT" }, \

{ "join",  join,  0, NULL, NULL,"", "Joins station set in DCT" }, \

{ "print_config",  print_wifi,  0, NULL, NULL,"",  "prints current wifi configuration" }, \

{ "scan",  scan_wifi,  0, NULL, NULL,"",  "prints current wifi configuration" }, \

{ "ping",  ping,  1, NULL, NULL,"<ip address>",  "pings wifi configuration" }, \

{ "disconnect", disconnect, 0, NULL, NULL, "",             "Dis-connects from AP" },

/* worker thread support functions */

int is_wifi_provisioned()

{

    int retval;

    wiced_bool_t device_configured; // Only need to read the first entry of DTC - avoid for memory to copy entire DCT.

    wiced_result_t result;

    device_configured = WICED_FALSE;

    result = WICED_SUCCESS;

    /* comment this the next line and this function code works with ThreadX (unable to detect configured flag */

    result = wiced_dct_read_with_copy(&device_configured,DCT_WIFI_CONFIG_SECTION,OFFSETOF(platform_dct_wifi_config_t, device_configured),sizeof(wiced_bool_t) );

    if  (result != WICED_SUCCESS)

    {

        return 0;

    }

    if (device_configured) {

        retval = 1;

    }

    else {

        retval = 0;

    }

    return retval;

}

/* worker thread */

void worker_thread(uint32_t arg) {

    while(1) {

        wiced_rtos_delay_milliseconds(5000); // Wait ensures other CPU ready

        if (is_wifi_provisioned() == 1) {

            WPRINT_APP_INFO(("Is provisioned.\n"));

        }

        else {

            WPRINT_APP_INFO(("waiting.\n"));

        }

    }

}

/*

* Holder function to call printing wifi configuration in dct..

*/

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

{

print_wifi_config_dct();

return 0;

}

/*

* Holder function to bring up client inerface

*/

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

{

/* Bring up the STA (client) interface ------------------------------------------------------- */

        wiced_network_up(WICED_STA_INTERFACE, WICED_USE_EXTERNAL_DHCP_SERVER, NULL);

        return 0;

}

/*

* Holder function to disconnect network

*/

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

{

wiced_network_down(WICED_STA_INTERFACE);

    return 0;

}

/*

* Holder function to store AP name and Pass phrase in DCT

*/

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

{

    char* ap_name = argv[1];

    char* ap_passkey = argv[2];

    platform_dct_wifi_config_t*     dct_wifi_config          = NULL;

    /* get the read lock */

    wiced_dct_read_lock( (void**) &dct_wifi_config, WICED_TRUE, DCT_WIFI_CONFIG_SECTION, 0, sizeof( *dct_wifi_config ) );

    /* store AP name and Pass phrase in DCT*/

    strcpy((char *)&dct_wifi_config->stored_ap_list[0].details.SSID.value[0],ap_name);

    dct_wifi_config->stored_ap_list[0].details.SSID.length = strlen(ap_name);

    strcpy((char *)&dct_wifi_config->stored_ap_list[0].security_key[0],ap_passkey);

    dct_wifi_config->stored_ap_list[0].security_key_length = strlen(ap_passkey);

    /* SSF added set flag */

    dct_wifi_config->device_configured = WICED_TRUE;

    wiced_dct_write( (const void*) dct_wifi_config, DCT_WIFI_CONFIG_SECTION, 0, sizeof(platform_dct_wifi_config_t) );

    /* release the read lock */

    wiced_dct_read_unlock( dct_wifi_config, WICED_TRUE );

    return WICED_SUCCESS;

}

/*

* Holder function to scan for Wi-Fi Access Points (AP)

*/

int scan_wifi(int argc, char *argv[]){

        wiced_time_t    scan_start_time;

        wiced_time_t    scan_end_time;

        app_scan_data_t scan_data;

        /* Initialize the semaphore that will tell us when the scan is complete */

        wiced_rtos_init_semaphore(&scan_data.semaphore);

        scan_data.result_count = 0;

        WPRINT_APP_INFO( ( "Waiting for scan results...\n" ) );

        WPRINT_APP_INFO( ("  # Type  BSSID             RSSI  Rate Chan  Security         SSID\n" ) );

        WPRINT_APP_INFO( ("----------------------------------------------------------------------------------------------\n" ) );

        /* Start the scan */

        wiced_time_get_time(&scan_start_time);

        wiced_wifi_scan_networks(scan_result_handler, &scan_data );

        /* Wait until scan is complete */

        wiced_rtos_get_semaphore(&scan_data.semaphore, WICED_WAIT_FOREVER);

        wiced_time_get_time(&scan_end_time);

        WPRINT_APP_INFO( ("\nScan complete in %lu milliseconds\n", (unsigned long )(scan_end_time - scan_start_time) ) );

        /* Clean up */

        wiced_rtos_deinit_semaphore(&scan_data.semaphore);

        return 0;

}

/*

* Callback function to handle scan results

*/

wiced_result_t scan_result_handler( wiced_scan_handler_result_t* malloced_scan_result )

{

    /* Validate the input arguments */

    wiced_assert("Bad args", malloced_scan_result != NULL);

    if ( malloced_scan_result != NULL )

    {

        app_scan_data_t* scan_data  = (app_scan_data_t*)malloced_scan_result->user_data;

        malloc_transfer_to_curr_thread( malloced_scan_result );

        if ( malloced_scan_result->status == WICED_SCAN_INCOMPLETE )

        {

            wiced_scan_result_t* record = &malloced_scan_result->ap_details;

            WPRINT_APP_INFO( ( "%3ld ", scan_data->result_count ) );

            print_scan_result(record);

            scan_data->result_count++;

        }

        else

        {

            wiced_rtos_set_semaphore( &scan_data->semaphore );

        }

        free( malloced_scan_result );

    }

    return WICED_SUCCESS;

}

static const command_t init_commands[] =

{

    DIAGNOSTICS_COMMANDS

    CMD_TABLE_END

};

/*

* Application start/main function.

*/

#define WORKER_STACK_SIZE (4096)

void application_start( )

{

    wiced_thread_t worker;

    /* Initialise the device */

    wiced_init( );

    WPRINT_APP_INFO( ( "\r\nType help to know more about commands ...\r\n" ) );

    command_console_init( STDIO_UART, MAX_LINE_LENGTH, line_buffer, MAX_HISTORY_LENGTH, history_buffer_storage, " " );

    console_add_cmd_table( init_commands );

    /* start wifi management thread */

    wiced_rtos_create_thread(&worker,WICED_DEFAULT_WORKER_PRIORITY,"worker_thread",worker_thread,WORKER_STACK_SIZE,NULL);

}

/*

* Print's Wi-Fi configuration in DCT

*/

static wiced_result_t print_wifi_config_dct( void )

{

    platform_dct_wifi_config_t* dct_wifi_config = NULL;

    if ( wiced_dct_read_lock( (void**) &dct_wifi_config, WICED_FALSE, DCT_WIFI_CONFIG_SECTION, 0, sizeof( *dct_wifi_config ) ) != WICED_SUCCESS )

    {

        return WICED_ERROR;

    }

    WPRINT_APP_INFO( ( "\r\n----------------------------------------------------------------\r\n\r\n") );

    /* Wi-Fi Config Section */

    WPRINT_APP_INFO( ( "Wi-Fi Config Section \r\n") );

    WPRINT_APP_INFO( ( "    device_configured               : %d \r\n", dct_wifi_config->device_configured ) );

    WPRINT_APP_INFO( ( "    stored_ap_list[0]  (SSID)       : %s \r\n", dct_wifi_config->stored_ap_list[0].details.SSID.value ) );

    WPRINT_APP_INFO( ( "    stored_ap_list[0]  (Passphrase) : %s \r\n", dct_wifi_config->stored_ap_list[0].security_key ) );

    WPRINT_APP_INFO( ( "    soft_ap_settings   (SSID)       : %s \r\n", dct_wifi_config->soft_ap_settings.SSID.value ) );

    WPRINT_APP_INFO( ( "    soft_ap_settings   (Passphrase) : %s \r\n", dct_wifi_config->soft_ap_settings.security_key ) );

    WPRINT_APP_INFO( ( "    config_ap_settings (SSID)       : %s \r\n", dct_wifi_config->config_ap_settings.SSID.value ) );

    WPRINT_APP_INFO( ( "    config_ap_settings (Passphrase) : %s \r\n", dct_wifi_config->config_ap_settings.security_key ) );

    WPRINT_APP_INFO( ( "    country_code                    : %c%c%d \r\n", ((dct_wifi_config->country_code) >>  0) & 0xff,

                                                                            ((dct_wifi_config->country_code) >>  😎 & 0xff,

                                                                            ((dct_wifi_config->country_code) >> 16) & 0xffff));

    WPRINT_APP_INFO( ( "    DCT mac_address                 : ") );

    print_mac_address( (wiced_mac_t*) &dct_wifi_config->mac_address );

    WPRINT_APP_INFO( ("\r\n") );

    wiced_dct_read_unlock( dct_wifi_config, WICED_FALSE );

    return WICED_SUCCESS;

}

Hello,

The pointer to variable that receives the thread handle (wiced_thread_t worker; ) is a local variable in the code attached in previous response. Kindly make it a global variable to solve the reset issue.

SeFe_4295646
Level 3
Level 3
First like received First like given

That appears to have solved the issue - many thanks!