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

How to Write flash , Read flash and delete flash from one location only.

Hello All,

I am working on the Nrf52810 board with sdk 14.2.

I have implemented the read ,write , delete feature in my code.

Now it is creating new entry for repeating/creating new record read write function each .

I wanted to read / write / delete in same location or (restrict in one location)

Here is my mainc file please check below.

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* Copyright (c) 2014 - 2017, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Please suggest how to read/write in same location without creating new record.

here is my debug output please check

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<info> app: Writing Record ID = 2
<info> app: Start searching...
<info> app: Found Record ID = 1
<info> app: Data =
<info> app: 0
<info> app: A2
<info> app: A3
<info> app: A4
<info> app: 22
<info> app: 2D
<info> app: C
<info> app: 20
<info> app: Found Record ID = 2
<info> app: Data =
<info> app: Heart Rate Sensor example started.
<info> app: Fast advertising.
<info> app: Writing Record ID = 3
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Waiting for your valuable response.

Regards,

Rohit

Parents
  • Hi Rohit,

    Cust to clarify: By "same location", do you mean the same address? If so, I would like to mention a few points just so we are on the same page:

    • Only full flash pages can be erased at a time, and this makes all bits '1' (FF...)
    • Writing to flash involved chancing some '1' to '0'
    • (Flash gets worn out, therefore it is useful with wear-leveling if you write much to the flash)

    The above is the main reason why you typically need a filesystem like a library such as FDS if you want to easily read and write flash data. And using the FDS approach, updating a record actually involves writing a new one, and marking the old as obsolete. This new record will be in a new location.

    If the above approach is not good in your use case (why?), the alternative to using FDS (or similar) is to access the flash (more) directly. This is what you have to do if you require the data to be at the same address every time. Then you can use the fstorage API for that. Just remember that you must delete the whole page whenever you want to update the data.

  • Hi Einar,

    Thanks for your clarification and response fds module.

    Ya same location means same memory location.

    As you mention it will recreate the new record as we call write again and again.

    Is that older record will store after deleting also because every time it wiil take new number for new record when we will call write function..?

    can you provide simple integrated  example for the fstorage.

    Waiting for your response

    Regards,

    Rohit

  • You can refer to the fstorage example in the SDK, but that is, unfortunately, a bit complex. You can also look at the example code in the fstorage documentation.

    Please note that using the simple approach where you always have data in the same flash location, have (at least) two major issues which you should consider if are acceptable or not:

    • You need to temporarily store the data in another location when the flash page is erased. If you store it in RAM, a reset at the "bad" time will cause the data to be lost.
    • There is no flash wear leveling. This is only a problem if you write very frequently to the flash, though.

    Hi Einar,

    Thanks for your valuable suggestion.

    Regards,

    Rohit

  • Hi,

    Yes With, FDS it goes like this:

    • Every time you write a new record, you get a new record.
    • Every time you delete a record, you mark it as dirty.
    • Every time you update a record, you actually write a new record with updated data, and mark the old as dirty.
    • Every time you run garbage collection, dirty records are deleted.

    This is how FDS works, and the reason is that it makes sense to use this approach for a flash file system (given the limitations of physical flash memory).

  • I have modified my main.c please check

    i wanted to read /write 2 element of array as i have declear in main.c

    uint8_t m_deadbeef[2] = {54,12} 

    But i can only access one element. and select element is showing 0.

    How i can access both the element .I have tried different methods but it is not working

    Please suggest any modification is required or any other issue is there..

    Here my New main.c file

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    /**
    * Copyright (c) 2014 - 2017, Nordic Semiconductor ASA
    *
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without modification,
    * are permitted provided that the following conditions are met:
    *
    * 1. Redistributions of source code must retain the above copyright notice, this
    * list of conditions and the following disclaimer.
    *
    * 2. Redistributions in binary form, except as embedded into a Nordic
    * Semiconductor ASA integrated circuit in a product or a software update for
    * such product, must reproduce the above copyright notice, this list of
    * conditions and the following disclaimer in the documentation and/or other
    * materials provided with the distribution.
    *
    * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
    * contributors may be used to endorse or promote products derived from this
    * software without specific prior written permission.
    *
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    my output window

    <info> app: Writing Record ID = 2

    <info> app: Start searching...

    <info> app: Found Record ID = 2

    <info> app: Data =
    <info> app: 0x 54
    <info> app: 0x 0
    <info> app:

  • Ok , Thanks for clarification...

  • Hi Rohit,

    There are two things I want to comment on here. First, the reason you get only the first element is that you are not doing what I suspect you meant to since you are not using pointers in a sensible way.

    You have:

    uint8_t *temp_data;
    On line 1072 you set the temp_data to the value of m_deadbeef[0]. So this means that the pointer temp_data  (which should hold an address), now instead holds the value 0x54. Then on line 1074 you do:
    record.data.p_data = &temp_data;
    So this means that you set the pointer to be written (record.data.p_data) to the address of the pointer temp_data. And since this pointer actually now is not a real pointer, but hold a data byte, this is the first byte that gets written. And the rest of the data that gets written is whatever comes in memory after that.

    There is also another problem: I think there is a misunderstanding with regard to word size here. Your m_deadbeef is two bytes long, but an FDS word is 4 bytes long. However, when you write the data in fds_test_write you specify that the length is sizeof(m_deadbeef)/sizeof(uint8_t), which is 2/1 = 2. And that corresponds to 8 bytes. So you write a record of 8 bytes, where the first two bytes are 54, 12, and the last six are whatever happens to be in memory after that.

    Einar

Reply
  • Hi Rohit,

    There are two things I want to comment on here. First, the reason you get only the first element is that you are not doing what I suspect you meant to since you are not using pointers in a sensible way.

    You have:

    uint8_t *temp_data;
    On line 1072 you set the temp_data to the value of m_deadbeef[0]. So this means that the pointer temp_data  (which should hold an address), now instead holds the value 0x54. Then on line 1074 you do:
    record.data.p_data = &temp_data;
    So this means that you set the pointer to be written (record.data.p_data) to the address of the pointer temp_data. And since this pointer actually now is not a real pointer, but hold a data byte, this is the first byte that gets written. And the rest of the data that gets written is whatever comes in memory after that.

    There is also another problem: I think there is a misunderstanding with regard to word size here. Your m_deadbeef is two bytes long, but an FDS word is 4 bytes long. However, when you write the data in fds_test_write you specify that the length is sizeof(m_deadbeef)/sizeof(uint8_t), which is 2/1 = 2. And that corresponds to 8 bytes. So you write a record of 8 bytes, where the first two bytes are 54, 12, and the last six are whatever happens to be in memory after that.

    Einar

Children
  • Hi Einar,

    Thanks for your correction and clarification on the FDS as i have misunderstood.

    I will work on your suggestion and let you know updates..

    Regards,

    Rohit

  • Made changes in code as per your suggestion but its showing some address.

    it is not showing some other data like below

    As i have declare uint8_t m_deadbeef[8] = {81,45,0,0,0,0,0,0};

    output

    <info> app: Found Record ID = 20

    <info> app: Data =
    <info> app: 0x 98
    <info> app: 0x 36
    <info> app: 0x 0
    <info> app: 0x 32
    <info> app: 0x 0
    <info> app: 0x 0
    <info> app: 0x 0
    <info> app: 0x 0
    <info> app:

    modified main.c

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    /**
    * Copyright (c) 2014 - 2017, Nordic Semiconductor ASA
    *
    * All rights reserved.
    *
    * Redistribution and use in source and binary forms, with or without modification,
    * are permitted provided that the following conditions are met:
    *
    * 1. Redistributions of source code must retain the above copyright notice, this
    * list of conditions and the following disclaimer.
    *
    * 2. Redistributions in binary form, except as embedded into a Nordic
    * Semiconductor ASA integrated circuit in a product or a software update for
    * such product, must reproduce the above copyright notice, this list of
    * conditions and the following disclaimer in the documentation and/or other
    * materials provided with the distribution.
    *
    * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
    * contributors may be used to endorse or promote products derived from this
    * software without specific prior written permission.
    *
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    What is causing while read/write operation

    Suggest any modification.

    Rohit

  • Hi Rohit,

    You still have problems with your input data, so you need to get this correct before going forward. Perhaps you should revise how pointers and arrays work in C, for instance looking here?

    I suggest you do something like this instead:

    Skip temp data, since m_deadbeef never changes. And do something like this:

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    record.file_id = FILE_ID_FDS_TEST;
    record.key = REC_KEY_FDS_TEST;
    record.data.p_data = m_deadbeef; // Note that there is no & here, since m_deadbeef if a pointer to the first element of the array (this is how arrays work in C)
    record.data.length_words = sizeof(m_deadbeef)/sizeof(uint32_t); // Note that we divide on the sizeof(uint32_t), since the FDS word size is 4 bytes
    ret_code_t ret = fds_record_write(&record_desc, &record);
    APP_ERROR_CHECK(ret);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    If the source data is not constant in the future, then you need to temporarily store the data as you attempted. But then you need to do it right, for instance doing something like this (note that here I put all code together, so it will not be exactly like this in a practical application):

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    uint8_t temp_data[sizeof(m_deadbeef)]; // Note that there is no * when declaring the array!
    memcpy(temp_data, m_deadbeef, sizeof(temp_data));
    record.file_id = FILE_ID_FDS_TEST;
    record.key = REC_KEY_FDS_TEST;
    record.data.p_data = temp_data; // Note that there is no & here, since temp_data if a pointer to the first element of the array (this is how arrays work in C)
    record.data.length_words = sizeof(temp_data)/sizeof(uint32_t); // Note that we divide on the sizeof(uint32_t), since the FDS word size is 4 bytes
    ret_code_t ret = fds_record_write(&record_desc, &record);
    APP_ERROR_CHECK(ret);
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • Thaks for your suggestion ,

    Perhaps you should revise how pointers and arrays work in C, for instance looking here?

    Okay i will do.

    I will let you know the regarding on this topic updates..

    Thanks And Regards,

    Rohit