External SPI flash interfere with SiP programming

Hello,

I am currently developing on a custom board with a nRF9160. So far so good.

I need to store some data in an external 8MB flash memory, via SPI (Windbond W25Q64JV). It took me some time to figure out the DeviceTree declaration, but it's finally working. I haven't tested much yet, but I can read/write data at the base address, using flash_write() and flash_read().

However, since I added the code for flash management, I am struggling to program my board. Once programmed, any subsequent programming attempt result in the following:

Flashing build_ns to 51001355
C:\Windows\system32\cmd.exe /d /s /c "west flash -d c:\Users\vince\OneDrive\Documents\GitLab_Firmware_Cellulaire\firmware_wna618\build_ns --skip-rebuild --dev-id 51001355"

-- west flash: using runner nrfjprog
-- runners.nrfjprog: Flashing file: c:\Users\vince\OneDrive\Documents\GitLab_Firmware_Cellulaire\firmware_wna618\build_ns\zephyr\merged.hex
[error] [ Client] - Encountered error -102: Command erase_file executed for 293 milliseconds with result -102          
[error] [  nRF91] - Failed while performing 'Erase' operation on target address 0x00000000.
-102: JLinkARM.dll WriteU32 returned error -1.
[error] [  nRF91] - Failed while erasing device. -102: JLinkARM.dll WriteU32 returned error -1.
[error] [ Worker] - JLinkARM.dll WriteU32 returned error -1.
ERROR: JLinkARM DLL reported an error. Try again. If error condition
ERROR: persists, run the same command again with argument --log, contact Nordic
ERROR: Semiconductor and provide the generated log.log file to them.
NOTE: For additional output, try running again with logging enabled (--log).
NOTE: Any generated log error messages will be displayed.
FATAL ERROR: command exited with status 33: nrfjprog --program 'c:\Users\vince\OneDrive\Documents\GitLab_Firmware_Cellulaire\firmware_wna618\build_ns\zephyr\merged.hex' --sectorerase --verify -f NRF91 --snr 51001355

Repeating the flashing attempt several times does not work. The workaround is to manually erase the SiP before programming again.

I am pretty sure that the SDK is storing the data to the external memory, because I can see some SPI frames on an oscilloscope. However, I have the feeling that it's interfering with the nRF9160 internal memory somehow ...

Here is the code I added for the memory management. When all this code is commented out, I can program and re-program normally.

prj.conf

# External FLASH memory on SPI
CONFIG_FLASH=y
CONFIG_SPI=y

devicetree

//----------------------------------------------------------------
// SPI 3 on P0.11, P0.12 and P0.13
// This SPI is used for the the external FLASH memory
//----------------------------------------------------------------
&spi3 {
	compatible = "nordic,nrf-spim"; //, "nordic,nrf-spim"; 
	status = "okay";
	pinctrl-0 = <&spi3_default>;
	pinctrl-1 = <&spi3_sleep>;
	pinctrl-names = "default", "sleep";
	cs-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;

	extflash0: extflash0@0 {
		compatible =  "jedec,spi-nor";
		reg = <0>;
		spi-max-frequency = <1000000>;	// Max supported by the flash is 133MHz
		jedec-id = [EF 40 17];	// JEDEC ID is [MF 7-0]=0xEF [ID 15-8]= [ID 7-0 = Size]=
		size = <DT_SIZE_M(64)>;
		has-dpd;
		t-enter-dpd = <3000>;	// TODO : Vérifier si ce timing est correct. DPD = Deep Power Down
		t-exit-dpd = <5000>;	// TODO : Vérifier si ce timing est correct		
		wp-gpios = <&gpio0 9 GPIO_ACTIVE_LOW>;
		hold-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
	};						
};


&pinctrl {
	spi3_default: spi3_default {
		group1 {
			psels = <NRF_PSEL(SPIM_SCK, 0, 13)>,
					<NRF_PSEL(SPIM_MOSI, 0, 11)>,
					<NRF_PSEL(SPIM_MISO, 0, 12)>;
		};
	};

	spi3_sleep: spi3_sleep {
		group1 {
			psels = <NRF_PSEL(SPIM_SCK, 0, 13)>,
					<NRF_PSEL(SPIM_MOSI, 0, 11)>,
					<NRF_PSEL(SPIM_MISO, 0, 12)>;
					low-power-enable;
		};
	};
};

[ ... ]

aliases {
	myspiflash= &extflash0;
};

The device tree also contains some definitions for the internal flash. Those were automatically generated when creating the project.

// Internal flash. Automatically generated by nRF
&flash0 {
	partitions {
		compatible = "fixed-partitions";
		#address-cells = <1>;
		#size-cells = <1>;

		boot_partition: partition@0 {
			label = "mcuboot";
			reg = <0x0 0x10000>;
		};
		slot0_partition: partition@10000 {
			label = "image-0";
			reg = <0x10000 0x40000>;
		};
		slot0_ns_partition: partition@50000 {
			label = "image-0-nonsecure";
			reg = <0x50000 0x30000>;
		};
		slot1_partition: partition@80000 {
			label = "image-1";
			reg = <0x80000 0x40000>;
		};
		slot1_ns_partition: partition@c0000 {
			label = "image-1-nonsecure";
			reg = <0xc0000 0x30000>;
		};
		scratch_partition: partition@f0000 {
			label = "image-scratch";
			reg = <0xf0000 0xa000>;
		};
		storage_partition: partition@fa000 {
			label = "storage";
			reg = <0xfa000 0x6000>;
		};
	};
};

My test code. Note that even when is removed, I still get the same programming error, which makes me think that the issue is on the DT.

static const struct device *flash_dev = DEVICE_DT_GET(DT_ALIAS(myspiflash));

void EXTERNAL_FLASH_Init(void)
{
    uint8_t i ;
    uint8_t buff_write [] = {10, 11, 12, 13, 14, 15 };
    uint8_t buff_read[10];
    

    struct flash_pages_info pageInfo ;


    if(device_is_ready(flash_dev))
    {   
    
        DEBUG_PRINT("External flash is composed of %d pages.\r\n", flash_get_page_count(flash_dev)) ;

        flash_get_page_info_by_offs(flash_dev, 0, &pageInfo) ;
        DEBUG_PRINT("First page size is %d \r\n", pageInfo.size) ;
        

        if(flash_write(flash_dev, 0, buff_write, sizeof(buff_write)) !=0){
            DEBUG_PRINT("Write failed !\r\n") ;
        } 
        
        if( flash_read(flash_dev, 0, buff_read, sizeof(buff_write)) != 0){
            DEBUG_PRINT("Read failed !\r\n") ;
        }

        for(i=0;i<sizeof(buff_write);i++)
        {
            DEBUG_PRINT("Index %d - Write: %d\tRead: %d\r\n", i, buff_write[i], buff_read[i]);            
        } 
    }
}

Thanks for your help.

Parents
  • Hello Vincent,

    Could you provide the complete logs for this run?

    Here is the code I added for the memory management. When all this code is commented out, I can program and re-program normally.
    My test code. Note that even when is removed, I still get the same programming error, which makes me think that the issue is on the DT.

    Would you have to remove both the memory related configs and DTS additions for it to work?

    Have you tried this using a DK? How are you flashing it?

    Regards,

    Elfving

  • Hi Elfving,

    I am flashing the board using a J-LINK Base, directly from VS Code. I've had not issue so far.

    I've tried the following :
    - Removing only the .c code, and keeping DTS and prj.conf  -> Can't program without manually erasing
    - Removing the .c code and DTS, and keeping and prj.conf -> Can't program without manually erasing
    - Removing the .c code, DTS and CONFIG_FLASH=y from prj.conf -> Programming works
    - Removing the .c code and CONFIG_FLASH=y, keeping DTS -> Programming works
    - Removing CONFIG_FLASH=y, and keeping the .c code and DTS -> Can't build, because functions such as flash_erase() are not defined.

    The CONFIG_FLASH=y seem to be the cause of my problem. However, I need it to enable the flash() functions.

    I am not not sur how to get the log. Where should I add "-- log" ?

    All these results are when clicking on the "Flash" text (orange circle). I just noticed that using the flash logo (green circle) works in all cases. I am confused about this, since both provide the same output on the terminal, and both initiate a flash erase of the nRF9160 prior to programming.

    Note that this is only possible for flashing, but not for debugging.

  • Vincent44 said:

    I am not not sur how to get the log. Where should I add "-- log" ?

    You can add it when flashing it from the commandline, I don't think there is an easy way of doing this with VSC "Actions". For instance open the build folder in a terminal by right clicking the build-folder in VSC, and select start new terminal here. Then run "nrfjprog --program \zephyr\zephyr.hex --log"

    Regards,

    Elfving

  • 1106.log.logProgramming using the terminal does not work.

    Attached the log when trying to program my nRF9160, that has been previously erase (aka, the case that works on VSCode).

  • Could you do one that hasn't been previously erased as well? It would be nice with one that shows the errors -102 and -1.

    Regards,

    Elfving

  • Attached are the 2 logs corresponding to the following steps:


    - Erase the SiP from VS Code
    - Try flashing using the command line : Failed
      -> Result in log_1.log
    - Flashing from VS Code : Success
    - Try flashing using the command line : Failed
      -> Result in log_2.log

    log_2.loglog_1.log

Reply Children
  • Hello again,

    It seems that I've overlooked that it doesn't work in command line no matter whether or not you've erased it.

    Have you modified the flashing Tasks in the VSC Actions? Are you seeing this issue when flashing anything else, like eg. the hello world sample?

    Could you provide me the hex file you are creating and flashing that is giving you this issue? 

    Regards,

    Elfving

  • Hello,
    No, I did not modify the flashing task in VS Code.

    Flashing/debugging works with this configuration :
     - Devicetree provides hardware info concerning the SPI / NVM (see below)
     - Nor SPI nor FLASH functions are used in the code.
     - In prf.conf, CONFIG_FLASH=n and CONFIG_SPI=y

    &spi3 {
        compatible = "nordic,nrf-spim";
        status = "okay";
        pinctrl-0 = <&spi3_default>;
        pinctrl-1 = <&spi3_sleep>;
        pinctrl-names = "default", "sleep";
    
        cs-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
        extflash0: extflash0@0 {
            compatible =  "jedec,spi-nor";
            #address-cells = <1>;
            #size-cells = <1>;
            
            reg = <0>;
            spi-max-frequency = <1000000>;    // Max supported by the flash is 133MHz
            jedec-id     = [EF 40 17];    // JEDEC ID is [MF 7-0]=0xEF [ID 15-8]= [ID 7-0 = Size]=
            size         = <DT_SIZE_M(64)>;
            has-dpd;                // Enable the Deep Power Down management
            t-enter-dpd    = <3000>;    // 3ns
            t-exit-dpd     = <20000>;    // Not 100% sure of this value.
            wp-gpios      = <&gpio0 9 GPIO_ACTIVE_LOW>;
            hold-gpios     = <&gpio0 10 GPIO_ACTIVE_LOW>;        
        };                            
    };
    
    &pinctrl {
        spi3_default: spi3_default {
            group1 {
                psels = <NRF_PSEL(SPIM_SCK, 0, 13)>,
                        <NRF_PSEL(SPIM_MOSI, 0, 11)>,
                        <NRF_PSEL(SPIM_MISO, 0, 12)>;
            };
        };
    
        spi3_sleep: spi3_sleep {
            group1 {
                psels = <NRF_PSEL(SPIM_SCK, 0, 13)>,
                        <NRF_PSEL(SPIM_MOSI, 0, 11)>,
                        <NRF_PSEL(SPIM_MISO, 0, 12)>;
                        low-power-enable;
            };
        };
    };



    When I set CONFIG_FLASH=y, even with the same C code, that does not call any function related to the flash, I get the error reported in my initial post when trying to flash or debug.

    Flashing build_ns to 51001355
    C:\Windows\system32\cmd.exe /d /s /c "west flash -d c:\Users\vince\OneDrive\Documents\GitLab_Firmware_Cellulaire\firmware_wna618\build_ns --skip-rebuild --dev-id 51001355"

    -- west flash: using runner nrfjprog
    -- runners.nrfjprog: Flashing file: c:\Users\vince\OneDrive\Documents\GitLab_Firmware_Cellulaire\firmware_wna618\build_ns\zephyr\merged.hex
    [error] [ Client] - Encountered error -102: Command erase_file executed for 217 milliseconds with result -102          
    [error] [  nRF91] - Failed while performing 'Erase' operation on target address 0x00000000.                            
    -102: JLinkARM.dll WriteU32 returned error -1.
    [error] [  nRF91] - Failed while erasing device. -102: JLinkARM.dll WriteU32 returned error -1.
    [error] [ Worker] - JLinkARM.dll WriteU32 returned error -1.
    ERROR: JLinkARM DLL reported an error. Try again. If error condition
    ERROR: persists, run the same command again with argument --log, contact Nordic
    ERROR: Semiconductor and provide the generated log.log file to them.
    NOTE: For additional output, try running again with logging enabled (--log).
    NOTE: Any generated log error messages will be displayed.
    FATAL ERROR: command exited with status 33: nrfjprog --program 'c:\Users\vince\OneDrive\Documents\GitLab_Firmware_Cellulaire\firmware_wna618\build_ns\zephyr\merged.hex' --sectorerase --verify -f NRF91 --snr 51001355


    I have the feeling that some definitions concerning the memory map are missing, but I don't know what/where.

    Here are the 2 merged.hex file I get when changing the state of CONFIG_FLASH in prj.conf

    merged_CONFIG_FLASH=n.hex

    merged_CONFIG_FLASH=y.hex

    Using J-Flash Lite, both these files can be flash in the nRF9160. However, the one with CONFIG_FLASH=y does not seem to work properly (I believe it's crashing at startup).

  • Could you try having CONFIG_FLASH enabled on a default sample to make sure that still works?

    Regards,

    Elfving

  • Hello,

    I am not sure to understand what test you are suggesting. Since I am working on a custom board, any sample code will require to add some configuration, which is most likely what is cause my issue.

    I am able to control my external memory (which I use to store some log). Read/write is working fine. The issue is only when programming : the device should be manually erased first, which is not the case when the FLASH is not used.

  • Hello again,

    Vincent44 said:
    Since I am working on a custom board, any sample code will require to add some configuration

    Yeah they would at minimum require you to to add the board configuration, though I think you can go without Kconfigs like CONFIG_FLASH. As config flash seems to break something, I figured it would be good test to see if you can build and flash something like blinky with it enabled.

    Vincent44 said:
    I am able to control my external memory (which I use to store some log). Read/write is working fine. The issue is only when programming : the device should be manually erased first, which is not the case when the FLASH is not used.

    This seems odd to me, as flashing from the command line doesn't work either way. Could you try and test if also this work with something default?

    Regards,

    Elfving

Related