NRF52840 Memory Layout

Hi guys,

I'm leading a project with the nrf52840 dongle connected to a Raspberry Pi via the GPIO header. 

The firmware updating options for the Nordic are a bit limited in the sense that the dongle needs DFU via USB port and I don't want to make this extra connection. So instead I'm exploring openocd for programming via the SWDIO & SWDCLK pins. I was able to get it to work with some ease but now I'm struggling to understand the flash memory regions. 

In my project, I'm using Bluetooth and my linker file looks something like this:

MEMORY
{
  FLASH (rx) : ORIGIN = 0x27000, LENGTH = 0xd9000
  RAM (rwx) :  ORIGIN = 0x20002300, LENGTH = 0x3dd00
}

Using the Nordic programming tool and dragging the hex file I can see the address starting in the position 0x27000 as expected and with the length of the program. Doing some calculations 0x27000+0xd9000 = 0x100000, so I was expecting the memory regions from 0x27000 to 0x100000 to be all program-related. However, when I type the command to erase everything from 0x27000 to 0x100000 the bootloader stops working, making me believe that I'm also messing with some bootloader regions... Is that true? Or it is openocd not working as expected?

Also, do you know in what region of the memory are the User Information Configuration Registers (UICR)? I want to avoid deleting it or erasing it by mistake since it would make the regulator use 1.8V instead of 3V.

Best regards,

Fernando Fontes

Parents
  • Hello,

    The bootloader occupies the end of the flash, starting from address 0xE0000. This means the bootloader has been erased in your case. If you want to restore it, you can program the hex file provided at the end of this tutorial nRF52840 Dongle Programming Tutorial 

    Also, do you know in what region of the memory are the User Information Configuration Registers (UICR)? I want to avoid deleting it or erasing it by mistake since it would make the regulator use 1.8V instead of 3V.

    The UICR starts at address 0x10001000, so it is mapped to a different memory range than the FLASH.

    Best regards,

    Vidar

  • Hi Vidar Berg,

    Thank you for the reply.

    So this means that the actual program length should be: B9000 instead of D9000? 

    Thank you,

  • Ok, so I can do something like: `flash erase_address 0x27000 0xD9000` to delete current APP and Bootloader and then `flash write_bank 0 nrf52840_xxaa.bin 0x27000` to set the new app? 

  • That seems to work but I'm a bit confused how the MCU knows where the program region is. Is the MBR that holds that information? With the program region pointed to the address 0x27000?

    Nevertheless, I might need to preserve the bootloader. Without the bootloader I'm not able to halt de NRF now. I'm receiving `[nrf52840.cpu] external reset detected` after trying to halt it... I was only able to halt it when in booloader (DFU) mode. 

  • Ok, so I can do something like: `flash erase_address 0x27000 0xD9000` to delete current APP and Bootloader and then `flash write_bank 0 nrf52840_xxaa.bin 0x27000` to set the new app? 

    The problem with that is that you will still have the bootloader start address stored in the UICR @ 0x10001014 which signals the MBR that a bootloader is present. In other words, when erasing the bootloader, you will also need to erase the UICR. 

    That seems to work

    It will work as long as the flash is erased @ 0xE0000, but if the application reaches this address, the MBR may think that a bootloader is present and try to boot it from that address.

    Is the MBR that holds that information?

    The entry point after reset is always 0x0, for more details, please refer to the Master boot record and SoftDevice reset procedure section of the softdevice specification.

    I'm not familiar with openocd, and got a 404 error when I tried to access the documentation now, but I assume it should have an 'eraseall' command to erase the chip so you can just re-program the Softdevice and app. 

    With regards to the REGOUT0  register, it can also be set at runtime before enabling the Softdevice:

        // Configure UICR_REGOUT0 register only if it is set to default value.
        if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) ==
            (UICR_REGOUT0_VOUT_DEFAULT << UICR_REGOUT0_VOUT_Pos))
        {
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
            NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~((uint32_t)UICR_REGOUT0_VOUT_Msk)) |
                                (UICR_REGOUT0_VOUT_3V0 << UICR_REGOUT0_VOUT_Pos);
    
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
    
            // System reset is needed to update UICR registers.
            NVIC_SystemReset();
        }

  • Ok now it is a lot clear to me. So right now the reason why it is working is because I've erased the memory from address 0x27000 with len of 0xD9000. No bootloader on 0xE0000 and softdevice points the application to 0x27000. However, if for some reason I write something to 0xE0000 it will stop working. Go it. 

    There is an erase all command. But the reason I don't want to do it is exactly because of the REGOUT0 register. That part is still a bit confusing to me. How can I enable it before Softdevice? Isn't the softdevice that runs first and then calls the program region 0x27000? Or your suggestion is to put that code on my application and since the softdevice will call the application the REGOUT0 gets updated and after SystemReset the voltage gets fixed again?

    Best,

  • There is an erase all command. But the reason I don't want to do it is exactly because of the REGOUT0 register. That part is still a bit confusing to me. How can I enable it before Softdevice?

    If you need to set it before the softdevice, then you will need use the debugger to write to it. Otherwise, you can run the code snippet I posted before initializing the Softdevice. This will update the register setting on first startup (UICR is in NV memory, so it will only need to be set once).

    code on my application and since the softdevice will call the application the REGOUT0 gets updated and after SystemReset the voltage gets fixed again?

    Yes.

Reply
  • There is an erase all command. But the reason I don't want to do it is exactly because of the REGOUT0 register. That part is still a bit confusing to me. How can I enable it before Softdevice?

    If you need to set it before the softdevice, then you will need use the debugger to write to it. Otherwise, you can run the code snippet I posted before initializing the Softdevice. This will update the register setting on first startup (UICR is in NV memory, so it will only need to be set once).

    code on my application and since the softdevice will call the application the REGOUT0 gets updated and after SystemReset the voltage gets fixed again?

    Yes.

Children
Related