NRF52832 - setting up NFFS for the external flash W25QXXDV


faisal.saleem@...
 

Hi

At the moment I am struggling to mount W25QXXDV external flash as NFFS. We have a custom board with nrf52832 connected to the external spi flash W25QXXDV. So Zephyr provides the driver for W25qxxdv, but without page layout implementation. I modified the driver by adding page layout support, simply copied from the nrf flash layout implementation.. given the size is 2MB, page size kept to 4096.. makes 512 pages... please correct me if I shouldn't be doing it... If I don't do it then I get kernel panic because there is no implementation. I know that PAGE_LAYOUT should be disabled to avoid it but one of the settings is overriding PAGE_LAYOUT to be activated even if I disable it.. 

#if defined(CONFIG_FLASH_PAGE_LAYOUT)
static struct flash_pages_layout dev_layout;
 
static void flash_W25QXXDV_pages_layout(struct device *dev,
     const struct flash_pages_layout **layout,
     size_t *layout_size)
{
dev_layout.pages_count = 512;
dev_layout.pages_size = 4096;
*layout = &dev_layout;
*layout_size = 1;
}
#endif /* CONFIG_FLASH_PAGE_LAYOUT */
 
static const struct flash_driver_api spi_flash_api = {
.read = spi_flash_wb_read,
.write = spi_flash_wb_write,
.erase = spi_flash_wb_erase,
.write_protection = spi_flash_wb_write_protection_set,
#if defined(CONFIG_FLASH_PAGE_LAYOUT)
#if 0
.page_layout = (flash_api_pages_layout)
       flash_page_layout_not_implemented,
#else
.page_layout = flash_W25QXXDV_pages_layout,
#endif
#endif
.write_block_size = 1};

I could also see that the nffs_mount function inside nffs_fs.c has hardcoded the flash id to 0.. does it indicate that NFFS is to be implemented only the internal flash... I have disabled that bit here and I am setting  "flash_desc" before entering the function and passing it through the input argument "mountp"... Please correct if my understanding is wrong.. e.g., 
                flash_desc.id = 1;
flash_desc.sector_count = flash_get_page_count(flash_dev);
flash_desc.area_offset = 0; //1044480;
flash_desc.area_size = 1048576;   //even though it is 2MB, I am only using 1MB for now...

static int nffs_mount(struct fs_mount_t *mountp)
{
struct nffs_flash_desc *flash_desc =
(struct nffs_flash_desc *)mountp->fs_data;
int cnt;
int rc;
 
/* Set flash device */
flash_dev = (struct device *)mountp->storage_dev;
 
/* Set flash descriptor fields */
#if 0
flash_desc->id = 0;
flash_desc->sector_count = flash_get_page_count(flash_dev);
flash_desc->area_offset = FLASH_AREA_STORAGE_OFFSET;
flash_desc->area_size = FLASH_AREA_STORAGE_SIZE;
#endif
rc = nffs_misc_reset();
if (rc) {
return -EIO;
}
 
cnt = CONFIG_NFFS_FILESYSTEM_MAX_AREAS;
rc = nffs_misc_desc_from_flash_area(flash_desc, &cnt, descs);
if (rc) {
return -EIO;
}
 
rc = nffs_restore_full(descs);
switch (rc) {
case 0:
break;
case FS_ECORRUPT:
rc = nffs_format_full(descs);
if (rc) {
return -EIO;
}
break;
default:
return -EIO;
}
 
return 0;}
So I could see that there is no "Lost+Found" directory inside the external flash, and when it tries to create it, it fails while writing.. thus I am getting -5 (EIO) message when I am trying to mount it...
Inside "nffs_restore_full" function, it does nffs_restore_area_contents(..) ... I could see activity on the pins when I probe it.. then it ensures that the file system contains a valid scratch area... then it ensures that the file system contains a valid root directory.. finally when it is trying to confirm, if there is a lost+found directory,.. which is not there, so it tries to create it and in turn writes to it, which fails... and it fails to mount...


my prj.conf looks like


CONFIG_FLASH_HAS_DRIVER_ENABLED=y
CONFIG_FLASH_HAS_PAGE_LAYOUT=y
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_SOC_FLASH_NRF=y
CONFIG_SOC_FLASH_NRF_RADIO_SYNC=y
CONFIG_SPI_FLASH_W25QXXDV=y
CONFIG_SPI_FLASH_W25QXXDV_SPI_NAME="SPI_1"
CONFIG_SPI_FLASH_W25QXXDV_DRV_NAME="W25QXXDV"
CONFIG_SPI_FLASH_W25QXXDV_INIT_PRIORITY=80
CONFIG_SPI_FLASH_W25QXXDV_SPI_FREQ_0=1000000
CONFIG_SPI_FLASH_W25QXXDV_SPI_SLAVE=1
CONFIG_SPI_FLASH_W25QXXDV_GPIO_SPI_CS=y
CONFIG_SPI_FLASH_W25QXXDV_GPIO_SPI_CS_DRV_NAME="GPIO_0"
CONFIG_SPI_FLASH_W25QXXDV_GPIO_SPI_CS_PIN=29
CONFIG_SPI_FLASH_W25QXXDV_GPIO_CS_WAIT_DELAY=50
CONFIG_SPI_FLASH_W25QXXDV_FLASH_SIZE=2097152
CONFIG_SPI_FLASH_W25QXXDV_DEVICE_ID=0x00ef4015
CONFIG_FS_FLASH_STORAGE_PARTITION=y
CONFIG_MPU_ALLOW_FLASH_WRITE=y
CONFIG_FS_NFFS_FLASH_DEV_NAME="W25QXXDV"
CONFIG_FILE_SYSTEM=y
CONFIG_FS_NFFS_NUM_BLOCKS=1024
CONFIG_FS_NFFS_NUM_INODES=1024
CONFIG_FS_NFFS_NUM_CACHE_BLOCKS=1
CONFIG_FS_NFFS_NUM_CACHE_INODES=1
CONFIG_FS_NFFS_NUM_DIRS=4
CONFIG_FS_NFFS_NUM_FILES=4
CONFIG_FS_NFFS_NUM_INODES=64
CONFIG_NFFS_FILESYSTEM_MAX_AREAS=64
CONFIG_NFFS_FILESYSTEM_MAX_BLOCK_SIZE=128

If there is an example where we are utilizing both internal and external flash as NFFS, that would be useful... 

Below is my dts file... I have modified it and I can easily make the internal flash work correctly as NFFS.. I can easily upload and download a file into the internal flash via mynewt from our mac computer, size around 23k. I had to reduce the maximum data chunk size for file upload and download from 512 to 256 or else it would give me errors and would never finish the transfer... Now I want to store images into the external flash which is why i need to setup NFFS on it..  


/dts-v1/;
#include <nordic/nrf52832.dtsi>
 
/ {
model = "Nordic PCA10040 Dev Kit";
compatible = "nordic,pca10040-dk", "nordic,nrf52832-qfaa",
     "nordic,nrf52832";
 
chosen {
zephyr,console = &uart0;
#ifdef CONFIG_MCUMGR_SMP_UART
zephyr,uart-mcumgr = &uart0;
#endif
zephyr,sram = &sram0;
zephyr,flash = &flash0;
};
};
 
&adc {
status ="ok";
};
 
&gpiote {
status ="ok";
};
 
&gpio0 {
status ="ok";
};
 
&uart0 {
status = "ok";
compatible = "nordic,nrf-uart";
current-speed = <115200>;
};
 
&i2c0 {
status = "ok";
sda-pin = <26>;
scl-pin = <27>;
};
 
&i2c1 {
status = "ok";
sda-pin = <30>;
scl-pin = <31>;
};
 
&flash0 {
/*
* For more information, see:
* http://docs.zephyrproject.org/devices/dts/flash_partitions.html
*/
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
 
boot_partition: partition@0 {
label = "mcuboot";
reg = <0x00000000 0xc000>;
};
slot0_partition: partition@c000 {
label = "image-0";
reg = <0x0000C000 0x32000>;
};
slot1_partition: partition@3e000 {
label = "image-1";
reg = <0x0003E000 0x32000>;
};
scratch_partition: partition@70000 {
label = "image-scratch";
reg = <0x00070000 0xa000>;
};
 
#if defined(CONFIG_FS_FLASH_STORAGE_PARTITION)
storage_partition: partition@7a000 {
label = "storage";
reg = <0x0007a000 0x00006000>;
};
#endif
};
};


Any help is appreciated, Thanks

Faisal

Join {devel@lists.zephyrproject.org to automatically receive all group messages.