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

Segger Embedded Studio(Crossworks). Write data to UICR.

Hello. I am trying to port bootloader project from SDK to SES. But I do not know how to write data to UICR.

Steps what I've done:

  1. My nRF52832_xAA_MemoryMap.xml looks like (I've added UICR section):
< !DOCTYPE Board_Memory_Definition_File> 
< root name="nRF52832_xxAA">
  < MemorySegment name="FLASH" start="0x00000000" size="0x00080000" access="ReadOnly" />
  < MemorySegment name="UICR" start="0x10001000" size="0x0000020C" access="ReadOnly" />
  < MemorySegment name="RAM" start="0x20000000" size="0x00010000" access="Read/Write" />
< /root>
  1. To my flash_placement I've added:
< MemorySegment name="$(FLASH_NAME:UICR)">
< ProgramSection alignment="4" size="0x04" load="Yes"  name=".uicrBootStartAddress" start="$(UICR_BOOTLOADER:0x10001014)" />
< ProgramSection alignment="4" size="0x04" load="Yes"  name=".uicrMbrParamsPageAddress" start="$(UICR_MBR_PARAM_PAGE:0x10001018)" />
< /MemorySegment>
  1. At main file I've declared:

volatile uint32_t m_uicr_bootloader_start_address attribute ((section(".uicrBootStartAddress"))) = 0x55555555;

So for now I just want to write 0x55555555 in address UICR_BOOTLOADER:0x10001014

Project compiles without any errors/warning. At map file I have (this is obviously only part of map file):

.uicrBootStartAddress
                0x10001014        0x4
                0x10001014                __uicrBootStartAddress_start__ = .
 *(.uicrBootStartAddress .uicrBootStartAddress.*)
                0x10001018                . = ALIGN (MAX ((__uicrBootStartAddress_start__ + 0x4), .), 0x4)
 *fill*         0x10001014        0x4 
                0x10001018                __uicrBootStartAddress_end__ = (__uicrBootStartAddress_start__ + SIZEOF (.uicrBootStartAddress))
                0x00000004                __uicrBootStartAddress_size__ = SIZEOF (.uicrBootStartAddress)
                0x10001018                __uicrBootStartAddress_load_end__ = __uicrBootStartAddress_end__
                0x00000001                . = ASSERT (((__uicrBootStartAddress_start__ == __uicrBootStartAddress_end__) || ((__uicrBootStartAddress_end__ >= __UICR_segment_start__) && (__uicrBootStartAddress_end__ <= __UICR_segment_end__))), error: .uicrBootStartAddress is too large to fit in UICR memory segment)
                0x10001018                __uicrMbrParamsPageAddress_load_start__ = 0x10001018
So it looks like, that .uicrBootStartAddress is in the right place.

After all this steps it should work, at least I've thought so. But when I erase my PCA10040 and download firmware to board, at address 0x10001014 I see only 0xFFFFFFFF:

C:\Program Files (x86)\Nordic Semiconductor\nrf5x\bin>nrfjprog.exe --memrd 0x10001014

0x10001014: FFFFFFFF |....|

(other firmware data is written to board without any problem - I see not 0xFFFFFFFF data from FLASH_START for bootloader (0x00072000)).

The question is: how to write data to UICR from Segger Embedded Stuido's project? Maybe I've done something wrong (forget something?) at the steps above?

  • Don't think that's going to work. The variable declaration isn't constant so it'll have reserved space in the UICR expecting to copy the variable in at runtime I think, which isn't what you want.

    Try making the variable static constant so it actually puts it in the file. Take a look at the ELF file as well.

  • After adding "static const" still have same problem. As for elf file... actualy, have not read elf files before. As I understand it should has all programm sections/segments in it. My elf file looks like 99% binary data and couple of strings including my ".uicrBootStartAddress".

  • SES should have a viewer for ELF files if you double click on it, see if there's anything in the file at the address you used.

    I just looked at one of my Crossworks (basically the same product) projects which has a UICR section, in fact it's just a UICR project and nothing else, I have this

    const struct
    {
    	uint8_t	MAC_ADDRESS[6];
    	char		PIN[6];
    	uint32_t	RESET_CODE;
    } RELAY_DATA  __attribute((section("uicr")))  = {
    	.MAC_ADDRESS = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
    	.PIN         = { '0', 0', '0', '0', '0', '0' },
    	.RESET_CODE  = 0x12345678,
    };
    

    The name of the section in the flash_placement file should be "UICR", not $(FLASH_NAME:UICR). That uses the value of FLASH_NAME if it exists and 'UICR' if it doesn't. Using just UICR is better, although I don't think that's your problem.

  • Elf file at the end has 0x00079690 - last data to be written to flash, and after that - 0x20002c00 - RAM. So nothing at UICR (0x10001014). I've changed $(FLASH_NAME:UICR) to "UICR", but in elf still no data for UICR address.

  • not much more to suggest at this point. Can't see an error, looks right to me and I have a couple of projects with UICR sections in them which I do that way.

    Only thing left to try, View-> Symbol Browser and use the search to find where that symbol has been put, assuming it's not decided that it isn't used and just removed it .. but I don't recall having to tell it to keep the data explicitly.

Related