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?

Parents
  • 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;
    }
    
Reply
  • 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;
    }
    
Children
Related