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

Writing to flash fails on nRF52840 Dongle, fine on nRF52840 DK

My problem is similar to this

https://devzone.nordicsemi.com/f/nordic-q-a/64696/projects-for-writing-into-flash-memory-does-not-work-on-nrf52840-dongle/264746#264746

except for one major difference.  I am using only SoftDevice and I disable SoftDevice before I do the writes. I follow the requirements by writing in small hunks. The code that does the write is as follows

    // Now we have to write the data in hunks into flash
    // Each page is 1024 bytes, and a write is in 4-byte hunks
    // So we will find the number of 1024 byte pages to write,
    // and then the number of 4-byte hunks left over.

    // Disable soft device so we don't have to deal with events
    sd_softdevice_disable();
    // Buffer to write to flash. Need to write it in four-byte hunks
    uint32_t *ptr32 = (uint32_t *)keysDataBuffer;
    while (true)
    {
        // Where to write
        addr = (uint32_t *)(pg_size * pg_num);
        // Erase page:
        while(true)
        {
            err_code = sd_flash_page_erase(pg_num);
            if (err_code == NRF_SUCCESS)
            {
                break;
            }
            if (err_code != NRF_ERROR_BUSY)
            {
                NRF_LOG_DEBUG("Erasing data returned error %u.", err_code);
                APP_ERROR_CHECK(err_code);
            }
        }
        i = (size >= pg_size) ? (pg_size >> 2) : (size >> 2);     // four-byte hunks to write; size is evenly divisible by four
        while(true)
        {
            err_code = sd_flash_write(addr, ptr32, i);
            if (err_code == NRF_SUCCESS)
            {
                break;
            }
            if (err_code != NRF_ERROR_BUSY)
            {
                NRF_LOG_DEBUG("Writing data returned error %u.", err_code);
                APP_ERROR_CHECK(err_code);
            }
        }
        size = size - pg_size;  // Subtract a page size from the total size
        if (size <= 0)          // if zero or less, all data has been written
        {
            break;
        }
        pg_num++;
        ptr32 = (uint32_t *)(keysDataBuffer + pg_size);
    }
    free(keysDataBuffer);
    NRF_LOG_DEBUG("Flash written");

The code works fine when running on the nRF52840 DK. What do I need to do to write to flash on the dongle? Clearly I cannot use NRF_LOG statements so I have used LED buttons to see how far I get and it does in the while loop.

   

Parents
  • Hi

    You're sure it's running as expected when using an nRF52840 DK, right? Because it seems like you're calling SoftDevice functions like sd_flash_page_erase() and sd_flash_write() after disabling the SoftDevice. Are you positive that the SoftDevice is disabled as expected? And why would you have to disable the SoftDevice? As long as you're not connected to another device or advertising, there should be a limited amount of SoftDevice interrupts occurring while writing to flash.

    Have you adapted the project to work on a Dongle as explained in the Dongle programming tutorial by changing the preprocessor definition BOARD_PCA10056 to BOARD_PCA10059? Also, where in the flash memory are you writing to? You might be running into examples on the Dongle if you're trying to I.E. overwrite the bootloader

    Best regards,

    Simon

Reply
  • Hi

    You're sure it's running as expected when using an nRF52840 DK, right? Because it seems like you're calling SoftDevice functions like sd_flash_page_erase() and sd_flash_write() after disabling the SoftDevice. Are you positive that the SoftDevice is disabled as expected? And why would you have to disable the SoftDevice? As long as you're not connected to another device or advertising, there should be a limited amount of SoftDevice interrupts occurring while writing to flash.

    Have you adapted the project to work on a Dongle as explained in the Dongle programming tutorial by changing the preprocessor definition BOARD_PCA10056 to BOARD_PCA10059? Also, where in the flash memory are you writing to? You might be running into examples on the Dongle if you're trying to I.E. overwrite the bootloader

    Best regards,

    Simon

Children
  • After a bunch of other issues which I have finally ironed out everything comes back down to this. Yes, the flash write works great on the DK. I did some extensive tests where I wrote to the flash and then read it right back, and it worked great. Of course on the DK, I have the ability to use NRF_LOG so I can see this in action.

    The documentation states that sd_flash_page_erase()  and sd_flash_write() will do their thing and then return when it is done  IF SoftDevice is disabled. The alternative is to leave SoftDevice enabled but this requires handling an event each call and then returning back to where one made the call to continue. That adds a great deal of complexity to the code as I am already tightly engaged using the sd_app_evt_wait() and sd_ble_evt_get() to handle fragmented notifications. That is the core part of this application and the last thing I want to do is place additional code in that loop to check for flash complete events. Writing to flash occurs rarely, only on disconnect if needed, whereas fragmented notifications happen repeatedly. That loop needs to be as efficient as possible especially when sending waveforms.

    IN any case, the documentation states I can clearly use these calls when SoftDevice is disabled, and the use of these calls is very simple. No complex asynchrony to handle.

    I have two projects that experience the same problem (Not surprising as they are based on the same code). Both work fine on the DK. The far more complicated project is the Generic Health Sensor which is configurable.. One can set defines to create different types of devices (Blood pressure, glucose meter, thermometer, Spirometer, weight scale, and pulse oximeter. Every time I switch projects a complete re-write of flash needs to be done as they have different pairing keys. On the DK this works. ON the dongle, the application dies right when I call sd_flash_page_erase()  which is the first part of the flash write. If I return just before this call, a system reset is done and the dongle lives and begins advertising again as it should. 

    I do switch from  BOARD_PCA10056 to BOARD_PCA10059 as I go from DK to dongle.

    The dongle does work like a charm until the disconnect and I do the flash write. If I power cycle the dongle, my GHS health device will restart but it will not have the correct pairing information, so I have to clear the pairing on my Android cliient app to work with it (No surprise). All I am saying here, is everything else works fine on the dongle. Death is on the  sd_flash_page_erase() call.

Related