<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Writing to nvram</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/66299/writing-to-nvram</link><description>I would like help in understanding the limitations of the NVRAM. The documentation for the nRF52840 and the nRF52832 are different. This is what the nRF52840 reads: 
 
 Do I understand correctly that, for any word in a 4K block, it can only be written</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Wed, 23 Sep 2020 15:54:43 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/66299/writing-to-nvram" /><item><title>RE: Writing to nvram</title><link>https://devzone.nordicsemi.com/thread/271172?ContentTypeID=1</link><pubDate>Wed, 23 Sep 2020 15:54:43 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:21eb7e76-682f-4229-a588-9dc02d47e24f</guid><dc:creator>RayFoulkes</dc:creator><description>&lt;p&gt;It would seem that my initial concerns were valid. The state of Gazell pairing, even in SDK version 17, is that it uses the nrf version of write to nvram which breaks the constraints of the nRF52840 device. On the other hand, despite not liking to patch Nordic supplied software for my project, changing the nrf_gzp*.* software from using nrf_nvmc.h to use nrfx_nvmc.h was not complicated, if a little tedious, since the function names have changed. The nrfx versions are totally re-written and, whilst not completely optimal (they can still try to write 0 multiple times), they do not do that for the whole 32bit word AFAIK, just for a written byte. Since the byte only gets written twice in gazell, that is within the constraints outlined for the nRF52840. So far the re-written routines seem to permit gazell to function properly although I have only tested it for my own project.&lt;/p&gt;
&lt;p&gt;So, to be honourable, Nordic ought to warn users implementing Gazell on nRF52840 (this report not being in the public domain) that they must change the Nordic software as I have done.&lt;/p&gt;
&lt;p&gt;In addition you really should update the Gazell software to use the nrfx versions of nvmc routines and publish that in the next SDK update.&lt;/p&gt;
&lt;p&gt;I am now sufficiently confident in the outcome of this enquiry. Thank you very much for your assistance. The case can be closed.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Writing to nvram</title><link>https://devzone.nordicsemi.com/thread/271171?ContentTypeID=1</link><pubDate>Tue, 08 Sep 2020 11:22:49 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:3b0561e7-cb1f-4460-af20-74fec6f082cd</guid><dc:creator>RayFoulkes</dc:creator><description>&lt;p&gt;Oh, oh, Am I misleading people here. I have just discovered that there are TWO versions of write to nvram and I am probably looking at the wrong one. The one that I have been analysing is nrf_nvmc_write_byte which is included in my project. It is still extant in sdk V17 and is one of only two .c program in the .hal subdirectory under &amp;quot;nrfx&amp;quot;. I have just found a version which is nrfx_nvmc_write_byte which is much more generic and, at first glance, looks like it doesn&amp;#39;t have the same problem. That is in&amp;nbsp;&lt;/p&gt;
&lt;p&gt;nRF5_SDK_17.0.0_9d13099\modules\nrfx\drivers\src&lt;/p&gt;
&lt;p&gt;I wish that someone had mentioned that I was using out-of date software as from SDK V16 - would have saved me some time. Also, how are users supposed to know when they can change from nrf to nrfx versions? I obviously missed something.&lt;/p&gt;
&lt;p&gt;So, I think I will close the case after a bit of study of how the nrfx version works simply with the remark that &amp;quot;If you continue to use the nrf versions on the nRF52840, you will be contravening the hardware limitations. Switch to those in nRF5_SDK_17.0.0_9d13099\modules\nrfx\drivers to avoid that&amp;quot;. Sigh.&lt;/p&gt;
&lt;p&gt;(edit) not so fast - being as the name is changed the software for gzp no longer links. I will have to look at how the old and new match and maybe edit gzp software which I am not too keen on. - more later.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Writing to nvram</title><link>https://devzone.nordicsemi.com/thread/271170?ContentTypeID=1</link><pubDate>Tue, 08 Sep 2020 10:53:15 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:dc1d41c0-6f92-44ae-87df-9fd33819be1a</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;&amp;quot;jira&amp;quot; is our internal issue tracker.&lt;/p&gt;
&lt;p&gt;Kenneth&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Writing to nvram</title><link>https://devzone.nordicsemi.com/thread/271169?ContentTypeID=1</link><pubDate>Tue, 08 Sep 2020 10:18:50 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:848a6452-0c58-481b-850f-c10502fa2cda</guid><dc:creator>RayFoulkes</dc:creator><description>&lt;p&gt;Hello, thank you for your response. There is an even more optimal solution where the demand zeros are checked against the existing zeros to avoid trying to re-write them. I will try to give a coding example. It isn&amp;#39;t very complicated.&lt;/p&gt;
&lt;p&gt;PS, what is &amp;quot;jira&amp;quot;?&lt;/p&gt;
&lt;p&gt;Regards, Ray&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Writing to nvram</title><link>https://devzone.nordicsemi.com/thread/271168?ContentTypeID=1</link><pubDate>Tue, 08 Sep 2020 10:07:16 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:02459126-0b82-4d6a-81d9-dc9e2fce4fa0</guid><dc:creator>Kenneth</dc:creator><description>&lt;p&gt;I have updated the internal jira case with your suggestions, I will let you know when I learn more.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Writing to nvram</title><link>https://devzone.nordicsemi.com/thread/271167?ContentTypeID=1</link><pubDate>Mon, 07 Sep 2020 17:02:31 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:fa8ed396-b597-4206-81ce-299aba3690d5</guid><dc:creator>RayFoulkes</dc:creator><description>&lt;p&gt;Just a suggestion to your software gurus, once you have checked that writing a 1 to an already written zero in nvram has no impact, here is my suggestion for a much simplified byte write routine:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;//Here is a suggestion. Perhaps only for the nRF52840??
//I have no test harness to check if it is valid.
//This is simple but relies entirely that writing a 1 to an existing zero does no harm.
//You have to be a bit careful in C with type casting here.

void nrf_nvmc_write_byte(uint32_t address, uint8_t value)
{
    uint32_t byte_shift = address &amp;amp; (uint32_t)0x03; //the address of the byte in a 32 bit word.
    uint32_t address32 = address &amp;amp; ~byte_shift; // Address of the word this byte is in.
    //Then, take the value to be written, negate it as 8 bits only, convert to 32 bits,
    //shift it into position and XOR to 0xFFFFFFFF.
    //Thus the result will all ones outside the byte to be written.
    uint32_t value32 = 0xFFFFFFFF ^ (((uint32_t)(uint8_t)(~value)) &amp;lt;&amp;lt; (byte_shift &amp;lt;&amp;lt; 3));

    // Enable write.
    NRF_NVMC-&amp;gt;CONFIG = (NVMC_CONFIG_WEN_Wen &amp;lt;&amp;lt; NVMC_CONFIG_WEN_Pos);
    __ISB();
    __DSB();
    //actually do the write.
    *(uint32_t*)address32 = value32;
    wait_for_flash_ready();

    NRF_NVMC-&amp;gt;CONFIG = (NVMC_CONFIG_WEN_Ren &amp;lt;&amp;lt; NVMC_CONFIG_WEN_Pos);
    __ISB();
    __DSB();
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Unless the same byte is written to more than once, zeros are only written once.&lt;/p&gt;
&lt;p&gt;I hope that I have given sufficient explanation and my proposal for modification is not too presumptious.&lt;/p&gt;
&lt;p&gt;Ray&lt;/p&gt;
&lt;p&gt;PS, there is a &amp;quot;word write&amp;quot; which I have not yet checked.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Writing to nvram</title><link>https://devzone.nordicsemi.com/thread/271166?ContentTypeID=1</link><pubDate>Mon, 07 Sep 2020 16:06:04 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:44432090-bcef-414c-91af-d614fa9758a1</guid><dc:creator>RayFoulkes</dc:creator><description>&lt;p&gt;Hello again. Sorry that this has taken so long. I have now updated to version 17 of the sdk and analysed the code of nrf_nvmc.c and my initial conclusions are not optimistic. I include the code below with my comments interspersed so the logic can be checked by one of Nordic engineers. Essentially the code makes no attempt to avoid re-writing zeros to the bytes NOT being written when the write_byte function is called. What it does is to install the values it wishes to write into the correct place in the 32 bit word, leaving the remainder of the word intact. Therefore to write zeros into the four bytes of a word guarantees that at least some of the zeros are written 4 times i.e. once for the first byte write, then repeated 3 more times for the remainder of the bytes.&lt;/p&gt;
&lt;p&gt;Here is the guilty code as far as I can see:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;void nrf_nvmc_write_byte(uint32_t address, uint8_t value)
{
    uint32_t byte_shift = address &amp;amp; (uint32_t)0x03; //the address of the byte in a 32 bit word.
    uint32_t address32 = address &amp;amp; ~byte_shift; // Address to the word this byte is in.
    //take the contents of the 32 bit word containing the addressed byte somewhere in it (up to&amp;gt;&amp;gt;).
    //Then shift 0xFF by four times the address of the byte i.e. byte 0 no shift, byte 3 by 12 bits.
    //Then Negate that and AND it with the word i.e. zero the contents of the byte to be written.
    //Thus value32 is the original nvram 32 bit word with the byte to be written zeroed.
    uint32_t value32 = (*(uint32_t*)address32 &amp;amp; ~((uint32_t)0xFF &amp;lt;&amp;lt; (byte_shift &amp;lt;&amp;lt; (uint32_t)3)));
    //Then, take the value to be written, shift it into position in a 32 bit word and add to value32.
    //Thus the result will be a new word value with the new value in it&amp;#39;s correct place in the word.
    value32 = value32 + ((uint32_t)value &amp;lt;&amp;lt; (byte_shift &amp;lt;&amp;lt; 3));

    // Enable write.
    NRF_NVMC-&amp;gt;CONFIG = (NVMC_CONFIG_WEN_Wen &amp;lt;&amp;lt; NVMC_CONFIG_WEN_Pos);
    __ISB();
    __DSB();
    //actually do the write.
    *(uint32_t*)address32 = value32;
    wait_for_flash_ready();

    NRF_NVMC-&amp;gt;CONFIG = (NVMC_CONFIG_WEN_Ren &amp;lt;&amp;lt; NVMC_CONFIG_WEN_Pos);
    __ISB();
    __DSB();
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Of course, I am not infallible so you will need a software engineer to check that.&lt;/p&gt;
&lt;p&gt;I cannot imagine why it would be difficult to fix - simply write 0xFF into all the other bytes instead of trying to install the byte value into the existing contents.&lt;/p&gt;
&lt;p&gt;Instead of reading the existing value, simply set the initial word value to 0xFFFFFFFF and apply all the same logic (or perhaps just OR the value in instead of using addition - a strange choice of the original author.&lt;/p&gt;
&lt;p&gt;It is as though the original author thought that zeros could be written back to ones, or is that the case with some of the Nordic chips??? Is it a question of conditional coding for the nrf52840 - the answer to those questions are beyond my knowledge.&lt;/p&gt;
&lt;p&gt;Once again, sorry to be rather slow to carry out the analysis.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Writing to nvram</title><link>https://devzone.nordicsemi.com/thread/271165?ContentTypeID=1</link><pubDate>Fri, 12 Jun 2020 12:16:54 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:dbf039e9-4d3a-4247-9ce0-b28f914bfb19</guid><dc:creator>RayFoulkes</dc:creator><description>&lt;p&gt;Sorry Runar, I have been overwhelmed this week. I will try to make some time over the weekend. Thanks for your attention.&lt;/p&gt;
&lt;p&gt;Ray&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Writing to nvram</title><link>https://devzone.nordicsemi.com/thread/271164?ContentTypeID=1</link><pubDate>Fri, 12 Jun 2020 11:05:21 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:14adf2b5-8766-4b3a-a5c4-14d4dcb1a37b</guid><dc:creator>run_ar</dc:creator><description>[quote user="RayFoulkes"]Presumeably, if the bit written 0 the first time, contains a 1 in the next 7&amp;nbsp; writes, that will be OK?[/quote]
&lt;p&gt;&amp;nbsp;Yes, that&amp;#39;s my understanding as well. Did you find time to check the write routine? I am afraid I did not this week, sorry for the inconvenience. Regardless I will register this write routine (the gazell part) as an internal issue so the SDK team can take a look. I have a feeling this is something that was not considered when porting the library to the new chip/platform.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Writing to nvram</title><link>https://devzone.nordicsemi.com/thread/271163?ContentTypeID=1</link><pubDate>Thu, 04 Jun 2020 09:57:39 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:1a618492-9a09-4c5a-8951-e8339d246bd8</guid><dc:creator>RayFoulkes</dc:creator><description>&lt;p&gt;Edit: OOPs, I failed to mention that this is from SDK 15.2 - I haven&amp;#39;t migrated yet to revised versions. I think 16 is the same though.&lt;/p&gt;
&lt;p&gt;Hello Runar, Ah, not being able to attempt to write 0 more than twice as opposed to not being able to write a 32 bit word more than twice, puts an entirely different light on the limitation. Presumeably, if the bit written 0 the first time, contains a 1 in the next 7&amp;nbsp; writes, that will be OK?&lt;/p&gt;
&lt;p&gt;I did not check whether all the bits already zero are set to 1 on the subsequent writes. That will take a bit of figuring out. Meanwhile, you will find the code in components\proprietary_rf\gzll\nrf_gzp_device.c specifically:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static void gzp_index_db_add(uint8_t val)
{
    int16_t i;
    uint8_t temp_val;
    uint32_t  addr;

    // Search for unwritten loacation in index DB
    for (i = 0; i &amp;lt; GZP_INDEX_DB_SIZE; i++)
    {
        temp_val = *(uint8_t*)(GZP_INDEX_DB_ADR + i);

        // Lower nibble
        if (i != (GZP_INDEX_DB_SIZE - 1))
        {
            if ((temp_val &amp;amp; 0x0f) == 0x0f)
            {
                temp_val = (temp_val &amp;amp; 0xf0) | val;
                break;
            }
            // Upper nibble
            else if ((temp_val &amp;amp; 0xf0) == 0xf0)
            {
                temp_val = (temp_val &amp;amp; 0x0f) | (val &amp;lt;&amp;lt; 4);
                break;
            }
        }
        else
        {
            temp_val = (GZP_PARAMS_DB_MAX_ENTRIES &amp;lt;&amp;lt; 4) | val;
            break;
        }
    }

    // Write index DB
    addr = (GZP_INDEX_DB_ADR + i);
    nrf_nvmc_write_byte(addr, temp_val);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;The &amp;quot;write byte&amp;quot; is in modules\nrfx\hal\nrf_nvmc.c and specifically is:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;void nrf_nvmc_write_byte(uint32_t address, uint8_t value)
{
    uint32_t byte_shift = address &amp;amp; (uint32_t)0x03;
    uint32_t address32 = address &amp;amp; ~byte_shift; // Address to the word this byte is in.
    uint32_t value32 = (*(uint32_t*)address32 &amp;amp; ~((uint32_t)0xFF &amp;lt;&amp;lt; (byte_shift &amp;lt;&amp;lt; (uint32_t)3)));
    value32 = value32 + ((uint32_t)value &amp;lt;&amp;lt; (byte_shift &amp;lt;&amp;lt; 3));

    // Enable write.
    NRF_NVMC-&amp;gt;CONFIG = (NVMC_CONFIG_WEN_Wen &amp;lt;&amp;lt; NVMC_CONFIG_WEN_Pos);
    __ISB();
    __DSB();

    *(uint32_t*)address32 = value32;
    wait_for_flash_ready();

    NRF_NVMC-&amp;gt;CONFIG = (NVMC_CONFIG_WEN_Ren &amp;lt;&amp;lt; NVMC_CONFIG_WEN_Pos);
    __ISB();
    __DSB();
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Had the specification been more specific, I would have checked the code carefully before troubling you with such details. I cannot afford the time today, but I will check carefully myself whether anything breaks the clarified restrictions you have given. It would be REALLY nice if you could persuade the specification writers to be more er, specific - your clarification makes a huge difference to the use of the nvram as a permanent data store.&lt;/p&gt;
&lt;p&gt;Many thanks for your response, I appreciate the support given by Nordic in such matters,&lt;/p&gt;
&lt;p&gt;Regards, Ray Foulkes&lt;/p&gt;
&lt;p&gt;PS, I was unable to preview the post prior to replying - it give an error. Apologies if it is messy.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Writing to nvram</title><link>https://devzone.nordicsemi.com/thread/271162?ContentTypeID=1</link><pubDate>Thu, 04 Jun 2020 08:13:06 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:edfc11dd-0827-4635-9b19-57821e515227</guid><dc:creator>run_ar</dc:creator><description>[quote user=""]Do I understand correctly that, for any word in a 4K block, it can only be written twice before the entire page must be erased?[/quote]
&lt;p&gt;&amp;nbsp;Yes, this is true for the 840. But more specifically the limitations is that you cannot write 0 to the same bit more than twice. In theory the flash allows 8 programs to the same address (but still the same bit cannot be programmed to ‘0’ more than twice). Can you point me to what file/line you are looking at for gazell pairing that does the writes? Thanks&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>