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

ULINK UICR programming

Is there any way to program UICR registers using Keil ULINK programmers?

I know that the algorithm it uses to program Flash does not support UICR. However, I am able to enter debug mode manually, change the NVMC-CONFIG to 1 and write into UICR registers. All manually.... Why can't it be automated by the tool?

  • I have not found the algorithm for writing to UICR in KEIL for nRF51 but if you install latest nrf-Tools here

    I see that it gives you option to write to nRF52 UICR registers in Keil settings like below image description

    and after adding this we can see that it adds the UICR address range like below image description

    Because both nrf51 and nrf52 have same NVMC interface and have same UICR config, I think this algorithm must be the same for nRF51. After you add this, you should be able to flash normally from Keil. Worth a try :)

  • You can also build one for nRF51 for Keil. (Need Chip Erase from other algorighm to work).

    I Added a pre compiled binary as uuencode below as well: nRF51_UICR_Permobil.FLM.

    This code is not so tested, but I'll work on it the comming days I think.

    Source FlashDev.c

    #include "..\FlashOS.H"        // FlashOS Structures
    
    struct FlashDevice const FlashDevice  =  {
       FLASH_DRV_VERS,             // Driver Version, do not modify!
       "nRF51_UICR_Permobil",      // Device Name 
       ONCHIP,                     // Device Type
       0x10001000,                 // Device Start Address
       0x00000100,                 // Device Size in Bytes (256B)
       4,                          // Programming Page Size
       0,                          // Reserved, must be 0
       0xFF,                       // Initial Content of Erased Memory
       100,                        // Program Page Timeout 100 mSec
       100,                        // Erase Sector Timeout 3000 mSec (set to short since this will fail anyway)
    
    // Specify Size and Address of Sectors
       0x04, 0x0,                  // Sector Size  4B (64 Sectors)
       SECTOR_END
    };
    

    Source FlashPrg.c

    #include "..\FlashOS.H"        // FlashOS Structures
    
    #define NVMC_BASE                 0x4001E000UL // Base address for NVMC
    #define NRF_NVMC                  ((NVMC_Peripheral_t*)NVMC_BASE)
    
    #define BLANK_DW                  0xFFFFFFFF
    #define NRF_CONFIG_WRITE_ENABLE   1
    #define NRF_CONFIG_WRITE_DISABLE  0
    
    #define UICR_START                0x10001000
    #define UICR_SIZE                 0x00000100
    
    typedef unsigned long uint32_t;
    
    typedef struct NVMC_Peripheral_t {
        uint32_t pad1[256];
        uint32_t READY;
        uint32_t pad2[64];
        uint32_t CONFIG;
    } NVMC_Peripheral_t;
    
    
    /**
     *  Initialize Flash Programming Functions
     *    Parameter:      adr:  Device Base Address
     *                    clk:  Clock Frequency (Hz)
     *                    fnc:  Function Code (1 - Erase, 2 - Program, 3 - Verify)
     *    Return Value:   0 - OK,  1 - Failed
     */
    int Init(unsigned long adr, unsigned long clk, unsigned long fnc)
    {
        return 0;
    }
    
    /**
     *  De-Initialize Flash Programming Functions
     *    Parameter:      fnc:  Function Code (1 - Erase, 2 - Program, 3 - Verify)
     *    Return Value:   0 - OK,  1 - Failed
     */
    int UnInit(unsigned long fnc)
    {
        return 0;
    }
    
    /**
     *  Erase complete Flash Memory
     *    Return Value:   0 - OK,  1 - Failed
     */
    int EraseChip(void)
    {
        // Report erase ok even though nothing is made
        // To fool programmer to think that erase was ok and allow programming
        return 0;
    }
    
    
    /**
     *  Erase Sector in Flash Memory
     *    Parameter:      adr:  Sector Address
     *    Return Value:   0 - OK,  1 - Failed
     */
    int EraseSector(unsigned long adr)
    {
        // Report erase ok even though nothing is made
        // To fool programmer to think that erase was ok and allow programming
        return 0;
    }
    
    /**
     * Perform bounds check and alignment check
     */
    int AddrCheck(unsigned long adr, unsigned long sz)
    {
        // Check bounds
        if ( (adr < UICR_START)
             || ((adr) >= (UICR_START + UICR_SIZE))
             || ((adr + sz) >= (UICR_START + UICR_SIZE)) )
            return 1;
    
        // Check alignment
        if ((adr | sz) & 0x03)
            return 1;
    
        return 0;
    }
    
    /**
     *  Program Page in Flash Memory
     *    Parameter:      adr:  Page Start Address
     *                    sz:   Page Size
     *                    buf:  Page Data
     *    Return Value:   0 - OK,  1 - Failed
     */
    int ProgramPage(unsigned long adr, unsigned long sz, unsigned char *buf)
    {
        if (AddrCheck(adr, sz))
            return 1;
    
        // Loop all dw:s in
        while (sz)
        {
            // Check for diff
            if ( *(uint32_t*)adr != *(uint32_t*)buf )
            {
                // Blank check
                if (*(uint32_t*)adr != BLANK_DW)
                    return 1;
    
                // Enable write
                NRF_NVMC->CONFIG = NRF_CONFIG_WRITE_ENABLE;
                while (!NRF_NVMC->READY)
                    ;
    
                // Write one DW
                *(uint32_t*)adr = *(uint32_t*)buf;
                while (!NRF_NVMC->READY)
                    ;
    
                // Disable write
                NRF_NVMC->CONFIG = NRF_CONFIG_WRITE_DISABLE;
                while (!NRF_NVMC->READY)
                    ;
    
                // Verify write
                if ( *(uint32_t*)adr != *(uint32_t*)buf )
                    return 1;
            }
    
            // Move to next location
            adr += 4;
            buf += 4;
            sz -= 4;
        }
    
        return 0;
    }
    
    /**
     * Verify content
     * Return end address checked, stop checking on error.
     * adr+sz on success
     */
    unsigned long Verify(unsigned long adr, unsigned long sz, unsigned char *buf)
    {
        if (AddrCheck(adr, sz))
            return adr;
    
        // Loop all dw:s in
        while (sz)
        {
            // Check for diff
            if ( *(uint32_t*)adr != *(uint32_t*)buf )
                return adr;
    
            // Move to next location
            adr += 4;
            buf += 4;
            sz -= 4;
        }
    
        return adr;
    }
    
    1. It seems that nrf52xxx_uicr.flm is not shipped with the nrf-Tools, but with the nrf_DeviceFamilyPack
    2. It is not working with my ULINK ME nor ULINKpro.
  • Tested ok. Either run with chip erase instead of block erase or rather, as I do, temporarily change to chip erase when content in UICR is changed.

  • Hi,

    Not sure I understand, is this suppose to apply to ULINK too ? 

Related