This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

How to enable High Voltage Mode of nRF5340 programmatically

Hi!

There are many questions regarding the high voltage mode of the nRF5340 already in this Q&A, but I don't see the answer to the question, how it is enabled programmatically.

This is working to set the voltage to 3.3V:

nrfjprog -f nrf53 --memwr 0x00FF8010 --val 5

But if I try to set the register in code like the following statement, the program halts at that point with no exception, error or restart of the processor.

NRF_UICR->VREGHVOUT = 0x5;

I even tried to set the register to 0xFFFFFFFD and it worked for the command line with nrfjprog but not programmatically.

Is there anything that I have to do before I'm allowed to write to this register?

Thank you very much

Parents
  • Hello,

    One way to do it is to use nrfjprog, as you have already tested. However, I actually did this on an nRF52840DK yesterday. Although the names of the registers are a bit different, and I didn't test this, you can try this function/snippet to change your UICR programatically:

    int change_gpio_voltage(uint32_t target_voltage)
    {
        int err = 0;
        #if defined(CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP)
        
        uint32_t regout = NRF_UICR->VREGHVOUT;
        LOG_INF("REGOUT = 0x%08x", regout);
        
        if ((regout & UICR_VREGHVOUT_VREGHVOUT_Msk)  != target_voltage) {
            LOG_INF("Target voltage not set. Configuring");
    
            // Set NVMC in write mode:
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
            while (NRF_NVMC->CONFIG != NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos) {
                // Wait...
            }
    
            // Write the actual UICR Register:
            NRF_UICR->VREGHVOUT = (target_voltage | ~UICR_VREGHVOUT_VREGHVOUT_Msk);
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
                // Wait...
            }
    
            // Set NVMC back in read mode:
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
            while (NRF_NVMC->CONFIG != NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos) {
                // Wait...
            }
            // Check whether it was set successfully:
            if ((NRF_UICR->VREGHVOUT & UICR_VREGHVOUT_VREGHVOUT_Msk) != target_voltage) {
                err = 0;
            }
            // Reset if success. Config will remain on future reboots.
            if (err == 0) {
                NVIC_SystemReset();
            }
        }
    
    
    
    
        return err;
        #else
        // implement for other chips
        return err;
        #endif
    }
    
    from main.c:
    
        change_gpio_voltage(UICR_VREGHVOUT_VREGHVOUT_3V3);

    Please note that you can only set the voltage register once. So you can do it like this, and it will only change it if it is not set. But you can't change back and forth between different voltages using this method.

    The reason is that you have to erase the UICR if you want to write to it again (nrfjprog --eraseall).

    Best regards,

    Edvin

Reply
  • Hello,

    One way to do it is to use nrfjprog, as you have already tested. However, I actually did this on an nRF52840DK yesterday. Although the names of the registers are a bit different, and I didn't test this, you can try this function/snippet to change your UICR programatically:

    int change_gpio_voltage(uint32_t target_voltage)
    {
        int err = 0;
        #if defined(CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP)
        
        uint32_t regout = NRF_UICR->VREGHVOUT;
        LOG_INF("REGOUT = 0x%08x", regout);
        
        if ((regout & UICR_VREGHVOUT_VREGHVOUT_Msk)  != target_voltage) {
            LOG_INF("Target voltage not set. Configuring");
    
            // Set NVMC in write mode:
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
            while (NRF_NVMC->CONFIG != NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos) {
                // Wait...
            }
    
            // Write the actual UICR Register:
            NRF_UICR->VREGHVOUT = (target_voltage | ~UICR_VREGHVOUT_VREGHVOUT_Msk);
            while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
                // Wait...
            }
    
            // Set NVMC back in read mode:
            NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
            while (NRF_NVMC->CONFIG != NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos) {
                // Wait...
            }
            // Check whether it was set successfully:
            if ((NRF_UICR->VREGHVOUT & UICR_VREGHVOUT_VREGHVOUT_Msk) != target_voltage) {
                err = 0;
            }
            // Reset if success. Config will remain on future reboots.
            if (err == 0) {
                NVIC_SystemReset();
            }
        }
    
    
    
    
        return err;
        #else
        // implement for other chips
        return err;
        #endif
    }
    
    from main.c:
    
        change_gpio_voltage(UICR_VREGHVOUT_VREGHVOUT_3V3);

    Please note that you can only set the voltage register once. So you can do it like this, and it will only change it if it is not set. But you can't change back and forth between different voltages using this method.

    The reason is that you have to erase the UICR if you want to write to it again (nrfjprog --eraseall).

    Best regards,

    Edvin

Children
No Data
Related