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.