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 Reply Children
  • Ok, I was already thinking that it might be something related to either CRC or missing writes to specify where the end/start of the program would be.

    If I delete the bootloader, at what address should I write the program for it to start? 

  • The start address will remain the same if you use the Softdevice. If not, you can place it at address 0x0 and overwrite the MBR.

  • 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();
        }

Related