Problems writing/reading struct to NVS

I've been slowly adding NVS functionality to my code.  Has been working fine, up until today when I attempted to write a struct I have for storing historical data to flash.

This is the struct:

struct log_data {
	// data structure to store individual strike events
	uint8_t	strike_level;  // SML = 1, MED = 2 or LRG = 4
	uint16_t	total_strike_count;  // Total number of strikes recorded to date
	struct bt_cts_current_time time_detected;  //Time stamp for each strike
};

I then have an array of this struct.  At this point, MAX_STRIKE_RECORDS = 10, but ultimately I want to see this at 250.

struct log_data lsr_strike_log[MAX_STRIKE_RECORDS];

In my code to read the data in from Flash, I have the following:

	uint32_t rc = 0;
	rc = nvs_read(&fs, HISTORY_ID, &lsr_strike_log, sizeof(lsr_strike_log));
	printk("sizeof = %u\n", sizeof(lsr_strike_log));
	printk("strike history rc = %u\n", rc);

The return value from nvs_read() is supposed to be the amount of data read in, if everything works as expected.  In my case, this should be equal to sizeof(lsr_strike_log), which is 160 bytes.  If the return value is larger than this, it apparently means there is more data to read in.  This is what I get from my two printk() statements:

sizeof = 160
strike history rc = 4294967294

So, its like the nvs_read() is going outside my defined flash area, or something - I'm not sure, hence why I'm posting here to see if someone can help me understand what's going on better.
My flash is initialised as per the following, and I don't get any of the error messages output via UART, so it appears to be initialising OK.
flash_dev = FLASH_AREA_DEVICE(STORAGE_NODE_LABEL);
	if (!device_is_ready(flash_dev)) {
		printk("Flash device %s is not ready\n", flash_dev->name);
		return -EINVAL;
	}
	fs.offset = FLASH_AREA_OFFSET(storage);
	rc = flash_get_page_info_by_offs(flash_dev, fs.offset, &info);
	if (rc) 
	{
		printk("Unable to get page info\n");
		return rc;
	}
	fs.sector_size = info.size;
	fs.sector_count = 3U;

	rc = nvs_init(&fs, flash_dev->name);
	if (rc) 
	{
		printk("Flash Init failed\n");
		return rc;
	}
If I enable CONFIG_LOG=y in my proj.config file, I see the following output:
I suspect I'm doing something obvious wrong. Problem is, its not obvious to me.
Thanks and regards,
Mike
Parents
  • Thanks Haakonsh.

    If I simplify what I'm trying to write to NVS, it seems to work OK.  I changed my data structure to just a simple array:

    uint16_t lsr_strike_log[9];

    And if I write/read this to NVS, I can see that the data is being stored.  I'm still getting weird values for the return value from nvs_write() and nvs_read() though.

    This is the log info I see when writing the simple array:

    If I try and write my struct to NVS in the form I ultimately want to, I crash my DK and it keeps rebooting.

    In my code I initialse NVS before I initialise anything to do with BLE, so not sure if the BLE initialisation then changes what I've done when setting up NVS?

    Thanks and regards,

    Mike

  • Hello Mike,

    What is the current state on this issue? 

    Best regards,

    Simon

  • Hi Simon,

    I’m just about to get back into this part of it after struggling with issues around GPIO/System OFF/MCUBoot for nearly a month.

    I’ll update this thread in a week or so when I’ve had a chance to do some more testing

    Cheers,

    Mike

  • Mike Austin (LPI) said:
    I’ll update this thread in a week or so when I’ve had a chance to do some more testing

    Sounds goodThumbsup

  • Hi Simon,

    I seem to have this working now.  Only problem is, I'm not able to get everything I want stored in NVS as I am running out of room.  And I'm not sure how to make more space, or indeed if I can.

    My struct takes up 12 bytes per array element, and I am trying to have capacity for up to 250 array elements.  At the moment, I hit a wall around 167.  I've got a few other bytes of info I store in NVS that are separate to this array - they take up about 15 bytes in total.

    This is how the flash is allocated in my .dts file (this is the default for the nRF52-DK)

    &flash0 {
    
    	partitions {
    		compatible = "fixed-partitions";
    		#address-cells = <1>;
    		#size-cells = <1>;
    
    		boot_partition: partition@0 {
    			label = "mcuboot";
    			reg = <0x00000000 0xc000>;
    		};
    		slot0_partition: partition@c000 {
    			label = "image-0";
    			reg = <0x0000C000 0x32000>;
    		};
    		slot1_partition: partition@3e000 {
    			label = "image-1";
    			reg = <0x0003E000 0x32000>;
    		};
    		scratch_partition: partition@70000 {
    			label = "image-scratch";
    			reg = <0x00070000 0xa000>;
    		};
    		storage_partition: partition@7a000 {
    			label = "storage";
    			reg = <0x0007a000 0x00006000>;
    		};
    	};
    };

    And this is how I have my flash device set up in my code (based on the example code)

    int16_t flash_initialise(void)
    {
        int16_t rc;
    
    	flash_dev = FLASH_AREA_DEVICE(STORAGE_NODE_LABEL);
    	if (!device_is_ready(flash_dev)) {
    		#ifdef DEBUG_NVS
    			printk("Flash device %s is not ready\n", flash_dev->name);
    		#endif
    		return -EINVAL;
    	}
    	printk("Flash device %s is ready\n",flash_dev->name);
    
    	fs.offset = FLASH_AREA_OFFSET(storage);
    	rc = flash_get_page_info_by_offs(flash_dev, fs.offset, &info);
    	if (rc !=0) 
    	{
    		#ifdef DEBUG_NVS		
    			printk("Unable to get page info\n");
    		#endif
    		return rc;
    	}
    	#ifdef DEBUG_NVS
    		printk("Page info OK\n");
    	#endif
    	fs.sector_size = info.size;
    	fs.sector_count = 2U;
    
    	rc = nvs_init(&fs, flash_dev->name);
    	if (rc !=0) 
    	{
    		#ifdef DEBUG_NVS
    			printk("Flash Init failed\n");
    		#endif
    		return rc;
    	}
    	#ifdef DEBUG_NVS
    		printk("Flash initialised OK\n");
    	#endif
    
    	// Check if data is stored in flash
    	rc = check_for_nvs_key();
    	return rc;
    	
    }

    As I understand it, the available flash storage size is 0x6000, which is about 24kB.  And I have allocated two sectors, each of 4096 bytes.

    So, I'm not sure why I'm running into storage problems.

    Sorry if this sounds like a pretty basic question, but I can't seem to find any info that would help me understand why I'm running out of storage space and how to increase it

    Cheers,

    Mike

Reply
  • Hi Simon,

    I seem to have this working now.  Only problem is, I'm not able to get everything I want stored in NVS as I am running out of room.  And I'm not sure how to make more space, or indeed if I can.

    My struct takes up 12 bytes per array element, and I am trying to have capacity for up to 250 array elements.  At the moment, I hit a wall around 167.  I've got a few other bytes of info I store in NVS that are separate to this array - they take up about 15 bytes in total.

    This is how the flash is allocated in my .dts file (this is the default for the nRF52-DK)

    &flash0 {
    
    	partitions {
    		compatible = "fixed-partitions";
    		#address-cells = <1>;
    		#size-cells = <1>;
    
    		boot_partition: partition@0 {
    			label = "mcuboot";
    			reg = <0x00000000 0xc000>;
    		};
    		slot0_partition: partition@c000 {
    			label = "image-0";
    			reg = <0x0000C000 0x32000>;
    		};
    		slot1_partition: partition@3e000 {
    			label = "image-1";
    			reg = <0x0003E000 0x32000>;
    		};
    		scratch_partition: partition@70000 {
    			label = "image-scratch";
    			reg = <0x00070000 0xa000>;
    		};
    		storage_partition: partition@7a000 {
    			label = "storage";
    			reg = <0x0007a000 0x00006000>;
    		};
    	};
    };

    And this is how I have my flash device set up in my code (based on the example code)

    int16_t flash_initialise(void)
    {
        int16_t rc;
    
    	flash_dev = FLASH_AREA_DEVICE(STORAGE_NODE_LABEL);
    	if (!device_is_ready(flash_dev)) {
    		#ifdef DEBUG_NVS
    			printk("Flash device %s is not ready\n", flash_dev->name);
    		#endif
    		return -EINVAL;
    	}
    	printk("Flash device %s is ready\n",flash_dev->name);
    
    	fs.offset = FLASH_AREA_OFFSET(storage);
    	rc = flash_get_page_info_by_offs(flash_dev, fs.offset, &info);
    	if (rc !=0) 
    	{
    		#ifdef DEBUG_NVS		
    			printk("Unable to get page info\n");
    		#endif
    		return rc;
    	}
    	#ifdef DEBUG_NVS
    		printk("Page info OK\n");
    	#endif
    	fs.sector_size = info.size;
    	fs.sector_count = 2U;
    
    	rc = nvs_init(&fs, flash_dev->name);
    	if (rc !=0) 
    	{
    		#ifdef DEBUG_NVS
    			printk("Flash Init failed\n");
    		#endif
    		return rc;
    	}
    	#ifdef DEBUG_NVS
    		printk("Flash initialised OK\n");
    	#endif
    
    	// Check if data is stored in flash
    	rc = check_for_nvs_key();
    	return rc;
    	
    }

    As I understand it, the available flash storage size is 0x6000, which is about 24kB.  And I have allocated two sectors, each of 4096 bytes.

    So, I'm not sure why I'm running into storage problems.

    Sorry if this sounds like a pretty basic question, but I can't seem to find any info that would help me understand why I'm running out of storage space and how to increase it

    Cheers,

    Mike

Children
Related