This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Use nrfx QSPI with Zephyr filesystem

I'm using Zephyr on a nRF52840 and I'd like to use the QSPI with the Fat Filesystem.   I added the following Config statements to prj.conf:


# Filesystem
CONFIG_FILE_SYSTEM=y
CONFIG_FAT_FILESYSTEM_ELM=y
CONFIG_NRFX_QSPI=y
CONFIG_DISK_ACCESS=y
CONFIG_DISK_ACCESS_SDHC=y
CONFIG_DISK_ACCESS_SPI_SDHC=y

The nrfx QSPI driver and file system code is then included in the build, but I'm unsure how to associate the QSPI with the filesystem.    I don't see a "CONFIG_DISK_ACCESS_QSPI_SDHC" to replace the "CONFIG_DISK_ACCESS_SPI_SDHC".    Or is there a different way to do this that I'm missing?

Thanks!

Parents
  • I looked into this, and it does not seem like there is added any support for QSPI with FAT Fs. To give you a better overview I'll provide you the call stack:

    • main()-->disk_access_init()  |  zephyr\samples\subsys\fs\fat_fs\src\main.c
      • disk->ops->init(disk) | zephyr\subsys\disk\disk_access.c
        • disk_spi_sdhc_access_init()-->  | if CONFIG_DISK_ACCESS_SPI_SDHC=y it will use functions from zephyr\subsys\disk\disk_access_spi_sdhc.c
          • spi_release() | zephyr\include\drivers\spi.h

    At the blue layer, there are different choices for hardware interface, as you can see in zephyr/subsys/disk, but there is none for QSPI.

    One option would be to create a driver yourself, in zephyr/subsys/disk/disk_access_spi_sdhc.c.

    You could also use the API \zephyr\include\drivers\flash.h and set these in prj.conf:

    CONFIG_FLASH=y
    CONFIG_SPI=y
    CONFIG_NORDIC_QSPI_NOR=y

    You may also get some good answers if you ask in any of these Zephyr resources:

    https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.4.0/zephyr/introduction/index.html#community-support

    Best regards,

    Simon

  • Simon,

    I've been looking into this and thought I'd try to get the SPI mode working, then see if I can modify disk_access_spi_sdhc.c to handle QSPI.

    Using one of the examples, I found that I needed to set:

    CONFIG_FILE_SYSTEM=y
    CONFIG_FAT_FILESYSTEM_ELM=y
    CONFIG_DISK_ACCESS=y
    CONFIG_DISK_ACCESS_SDHC=y
    CONFIG_SPI=y
    CONFIG_SPI_2=y
    CONFIG_DISK_ACCESS_SPI_SD

    to get the appropriate drivers to load.   Since I'm already using TWIM1 (via CONFIG_NRFX_TWIM1=y) and needed to write my own handler so multiple threads can share the I2C, I use the statement:

    IRQ_CONNECT(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQn,6,nrfx_isr,nrfx_twim_1_irq_handler,0);

    to catch the signal from the TWIM.    The TWIM handler seems to be working correctly...

    However, this seems to cause a conflict in the isr table.   When I compile with the SPI configs, I get the error:

    1> Combining ‘zephyr/isr_tables.c’
    1> gen_isr_tables.py: error: multiple registrations at table_index 4 for irq 4 (0x4)
    1> Existing handler 0x2ef09, new handler 0x2ef09
    1> Has IRQ_CONNECT or IRQ_DIRECT_CONNECT accidentally been invoked on the same irq multiple times?

    Commenting out my IRQ_CONNECT call removes the error, but also removes my ability to catch the signal from TWIM1 for my handler.

    I seem to remember reading (somewhere) that nRF52840 serial peripherals share index numbers leading me to think that I should be using SPI2 for the SDcard access.    Do you know if the disk_access code hard codes using SPI1?  Or is there some other conflict causing the problem with the isr table?

    Thanks...

  • Sorry for the delay on this. Have you made any progress lately? I'll look into your issue today/tomorrow.

  • Hi Simon,

    Yes, I was able to get a better understanding of what was happening via the Zephyr/Slack group.   I was trying to control the configuration via CONFIG statements.   I guess I didn't understand that most of the configuration is done via device-tree (via okay/disabled status, or other parameter modifications) overlay files.   My case was more confusing in that I want to use the non-blocking feature of TWIM so that most I2C activities are performed in the background.   The "stock" I2C/Nordic driver in Zephyr doesn't expose the interrupt handler (which I need to catch the completion signal/interrupt and start the next job in the queue).   So I had to disable the TWIM instance via device-tree, but enable it via CONFIG, since when enabling via device-tree, the internal interrupt is connected via "IRQ_CONNECT" (and I need to do that in my code to handle the interrupt myself).  If IRQ_CONNECT is called in both places, I get the error mentioned above.   This sort of goes against the device-tree guidance.   Evidently the device-tree methodology is replacing the CONFIG methodology, but for now both appear to be in place, so it is a bit confusing.

    Now that I more fully understand device-tree, I see its value in making things "more convenient" and perhaps making it easier to keep things consistent over multiple vendor devices.  But it also "hides" a lot of things that historically have been more visible in user code.   (I have always put "config" calls as the first things in my code.  So it would be very easy to determine what was being configured by glancing at the beginning of the code.   Now most of that work is hidden (for better or worse) in initialization code (or MACROS) inside the driver code.)  I guess I have to "get with the times"!!

    Thanks very much for your help!

Reply
  • Hi Simon,

    Yes, I was able to get a better understanding of what was happening via the Zephyr/Slack group.   I was trying to control the configuration via CONFIG statements.   I guess I didn't understand that most of the configuration is done via device-tree (via okay/disabled status, or other parameter modifications) overlay files.   My case was more confusing in that I want to use the non-blocking feature of TWIM so that most I2C activities are performed in the background.   The "stock" I2C/Nordic driver in Zephyr doesn't expose the interrupt handler (which I need to catch the completion signal/interrupt and start the next job in the queue).   So I had to disable the TWIM instance via device-tree, but enable it via CONFIG, since when enabling via device-tree, the internal interrupt is connected via "IRQ_CONNECT" (and I need to do that in my code to handle the interrupt myself).  If IRQ_CONNECT is called in both places, I get the error mentioned above.   This sort of goes against the device-tree guidance.   Evidently the device-tree methodology is replacing the CONFIG methodology, but for now both appear to be in place, so it is a bit confusing.

    Now that I more fully understand device-tree, I see its value in making things "more convenient" and perhaps making it easier to keep things consistent over multiple vendor devices.  But it also "hides" a lot of things that historically have been more visible in user code.   (I have always put "config" calls as the first things in my code.  So it would be very easy to determine what was being configured by glancing at the beginning of the code.   Now most of that work is hidden (for better or worse) in initialization code (or MACROS) inside the driver code.)  I guess I have to "get with the times"!!

    Thanks very much for your help!

Children
Related