Controlling GPIO within nrfjprog

Hello,

I have a product with QSPI flash that I would like to use nrfjprog to program the flash part. However, the QSPI flash's VCC is controlled (via a FET) from a GPIO line. I am looking for a way to have nrfjprog enable the GPIO line before attempting to access the QSPI flash (so that the flash is powered up). Is there a way from qspiinit.ini to do this?

Thanks,

Jon

Parents
  • Hello Jon,

    Unfortunately, nrfjprog currently does not have a setting to let you define the IO state for a particular GPIO during QSPI programming. I will make a feature request for it internally. In the meantime, maybe you can use pynrfjprog instead. Here is an example script proposed by one of the developers:

    from pynrfjprog import LowLevel
    from pathlib import Path
    import logging
    # Uncomment to enable verbose log output
    # logging.basicConfig(level=logging.DEBUG)
    target_cp = LowLevel.CoProcessor.CP_APPLICATION
    debugger_snr = 960158306 # Update with your snr here
    hex_to_flash = Path('qspi_hex.hex')
    if not hex_to_flash.exists():
        raise AssertionError(f"Selected hex {hex_to_flash} file does not exist")
    with LowLevel.API("NRF53", log=True) as api:
        # Connect and halt target core
        print("Connect to target")
        api.connect_to_emu_with_snr(debugger_snr)
        api.enable_coprocessor(target_cp)
        api.select_coprocessor(target_cp)
        api.connect_to_device()
        api.halt()
        # Disable MPU/SPU if enabled. Behaviour is device spesific.
        # For nRF53 it will issue a system reset w/halt
        print("Disable bprot")
        api.disable_bprot()
        
        # Example set GPIO P0.31 low (will light up LED4 on nRF53 DK)
        # Refer to device datasheet for addresses and values
        print("Set pin low")
        pin = 31
        gpio_base = 0x50842500
        gpio_dirset = gpio_base + 0x018
        gpio_outclr = gpio_base + 0x00C
        val = (1 << pin)
        api.write_u32(gpio_dirset, val, False)
        api.write_u32(gpio_outclr, val, False)
        # Enable qspi module
        api.qspi_init()
        
        # Do the programming yourself using QSPI functions
        addr = 0 # Address 0 is start of QSPI 
        data_len = 100
        data = list(range(0, data_len)) # data = [0,1,2,3 ... , 99]
        api.qspi_erase(addr, LowLevel.QSPIEraseLen.ERASE4KB) # Erase first page
        api.qspi_write(addr, data) # Write data
        # Read and verify
        device_data = api.qspi_read(addr, data_len) 
        assert data == list(device_data)
        # Optionally reset programmed device
        print("Applying pin reset")
        api.pin_reset()
        print("Done")

    Optionally you can try to use the program_file function. But we do not guarantee that there will not be a reset during programming (which will result in the GPIO being reset

    from pynrfjprog import LowLevel
    from pathlib import Path
    import logging
    # Uncomment to enable verbose log output
    # logging.basicConfig(level=logging.DEBUG)
    target_cp = LowLevel.CoProcessor.CP_APPLICATION
    debugger_snr = 960158306 # Update with your snr here
    hex_to_flash = Path('qspi_hex.hex')
    if not hex_to_flash.exists():
        raise AssertionError(f"Selected hex {hex_to_flash} file does not exist")
    with LowLevel.API("NRF53", log=True) as api:
        # Connect and halt target core
        print("Connect to target")
        api.connect_to_emu_with_snr(debugger_snr)
        api.enable_coprocessor(target_cp)
        api.select_coprocessor(target_cp)
        api.connect_to_device()
        api.halt()
        # Disable MPU/SPU if enabled. Behaviour is device spesific.
        # For nRF53 it will issue a system reset w/halt
        print("Disable bprot")
        api.disable_bprot()
        
        # Example set GPIO P0.31 low (will light up LED4 on nRF53 DK)
        # Refer to device datasheet for addresses and values
        print("Set pin low")
        pin = 31
        gpio_base = 0x50842500
        gpio_dirset = gpio_base + 0x018
        gpio_outclr = gpio_base + 0x00C
        val = (1 << pin)
        api.write_u32(gpio_dirset, val, False)
        api.write_u32(gpio_outclr, val, False)
        # Program your hex file
        print("Programming device")
        api.erase_file(hex_to_flash) # Optional: erase memory before writing
        api.program_file(hex_to_flash)
        api.verify_file(hex_to_flash) # Optional: verify after write
        # Optionally reset programmed device
        print("Applying pin reset")
        api.pin_reset()
        print("done")

    Best regards,

    Vidar

  • I will make a feature request for it internally.

    Was this ever implimented/planned?

  • Unfortunately it did not end up being added. Are you programming with nrfutil or nrfjprog? I suspect it may be easiest to create a batch script that first loads a minimal FW that asserts the GPIO and enable flash, and then starts the serial programming. It is also possible that you may be able to perform memory writes and configure the GPIO directly with nrfutil device without the chip being reset afterward.

Reply
  • Unfortunately it did not end up being added. Are you programming with nrfutil or nrfjprog? I suspect it may be easiest to create a batch script that first loads a minimal FW that asserts the GPIO and enable flash, and then starts the serial programming. It is also possible that you may be able to perform memory writes and configure the GPIO directly with nrfutil device without the chip being reset afterward.

Children
Related