添加qspi存储w25q128
添加littlefs文件系统 存储挂载路径/sys
This commit is contained in:
1 parent
c7cf944e61
commit
1f345bd81f
47 files changed
+21878
-103
No files matched your search
@@ -128,7 +128,7 @@ CONFIG_DFS_USING_WORKDIR=y
|
||||
CONFIG_DFS_FD_MAX=16
|
||||
CONFIG_RT_USING_DFS_V1=y
|
||||
# CONFIG_RT_USING_DFS_V2 is not set
|
||||
CONFIG_DFS_FILESYSTEMS_MAX=4
|
||||
CONFIG_DFS_FILESYSTEMS_MAX=6
|
||||
CONFIG_DFS_FILESYSTEM_TYPES_MAX=4
|
||||
CONFIG_RT_USING_DFS_ELMFAT=y
|
||||
|
||||
@@ -164,7 +164,12 @@ CONFIG_RT_USING_DFS_TMPFS=y
|
||||
# CONFIG_RT_USING_DFS_MQUEUE is not set
|
||||
# end of DFS: device virtual file system
|
||||
|
||||
# CONFIG_RT_USING_FAL is not set
|
||||
CONFIG_RT_USING_FAL=y
|
||||
# CONFIG_FAL_DEBUG_CONFIG is not set
|
||||
CONFIG_FAL_DEBUG=0
|
||||
CONFIG_FAL_PART_HAS_TABLE_CFG=y
|
||||
CONFIG_FAL_USING_SFUD_PORT=y
|
||||
CONFIG_FAL_USING_NOR_FLASH_DEV_NAME="W25Q128"
|
||||
|
||||
#
|
||||
# Device Drivers
|
||||
@@ -188,7 +193,7 @@ CONFIG_RT_SERIAL_RB_BUFSZ=512
|
||||
# CONFIG_RT_USING_ZERO is not set
|
||||
# CONFIG_RT_USING_RANDOM is not set
|
||||
# CONFIG_RT_USING_PWM is not set
|
||||
# CONFIG_RT_USING_MTD_NOR is not set
|
||||
CONFIG_RT_USING_MTD_NOR=y
|
||||
# CONFIG_RT_USING_MTD_NAND is not set
|
||||
# CONFIG_RT_USING_PM is not set
|
||||
CONFIG_RT_USING_RTC=y
|
||||
@@ -205,7 +210,12 @@ CONFIG_RT_USING_SPI=y
|
||||
# CONFIG_RT_USING_SPI_BITOPS is not set
|
||||
CONFIG_RT_USING_QSPI=y
|
||||
CONFIG_RT_USING_SPI_MSD=y
|
||||
# CONFIG_RT_USING_SFUD is not set
|
||||
CONFIG_RT_USING_SFUD=y
|
||||
CONFIG_RT_SFUD_USING_SFDP=y
|
||||
CONFIG_RT_SFUD_USING_FLASH_INFO_TABLE=y
|
||||
CONFIG_RT_SFUD_USING_QSPI=y
|
||||
CONFIG_RT_SFUD_SPI_MAX_HZ=50000000
|
||||
# CONFIG_RT_DEBUG_SFUD is not set
|
||||
# CONFIG_RT_USING_ENC28J60 is not set
|
||||
# CONFIG_RT_USING_SPI_WIFI is not set
|
||||
# CONFIG_RT_USING_WDT is not set
|
||||
@@ -660,7 +670,31 @@ CONFIG_PKG_SQLITE_DB_NAME_MAX_LEN=64
|
||||
CONFIG_PKG_USING_SQLITE_V3193=y
|
||||
# CONFIG_PKG_USING_RTI is not set
|
||||
# CONFIG_PKG_USING_DFS_YAFFS is not set
|
||||
# CONFIG_PKG_USING_LITTLEFS is not set
|
||||
CONFIG_PKG_USING_LITTLEFS=y
|
||||
CONFIG_PKG_LITTLEFS_PATH="/packages/system/littlefs"
|
||||
# CONFIG_PKG_USING_LITTLEFS_V090 is not set
|
||||
# CONFIG_PKG_USING_LITTLEFS_V170 is not set
|
||||
# CONFIG_PKG_USING_LITTLEFS_V172 is not set
|
||||
# CONFIG_PKG_USING_LITTLEFS_V201 is not set
|
||||
# CONFIG_PKG_USING_LITTLEFS_V205 is not set
|
||||
# CONFIG_PKG_USING_LITTLEFS_V214 is not set
|
||||
# CONFIG_PKG_USING_LITTLEFS_V220 is not set
|
||||
# CONFIG_PKG_USING_LITTLEFS_V221 is not set
|
||||
# CONFIG_PKG_USING_LITTLEFS_V230 is not set
|
||||
# CONFIG_PKG_USING_LITTLEFS_V250 is not set
|
||||
# CONFIG_PKG_USING_LITTLEFS_V293 is not set
|
||||
CONFIG_PKG_USING_LITTLEFS_V2112=y
|
||||
# CONFIG_PKG_USING_LITTLEFS_LATEST_VERSION is not set
|
||||
CONFIG_LFS_READ_SIZE=256
|
||||
CONFIG_LFS_PROG_SIZE=256
|
||||
CONFIG_LFS_BLOCK_SIZE=4096
|
||||
CONFIG_LFS_CACHE_SIZE=256
|
||||
CONFIG_LFS_BLOCK_CYCLES=500
|
||||
# CONFIG_DFS_LFS_READONLY is not set
|
||||
CONFIG_LFS_THREADSAFE=y
|
||||
CONFIG_LFS_LOOKAHEAD_MAX=128
|
||||
CONFIG_RT_DEF_LFS_DRIVERS=2
|
||||
CONFIG_PKG_LITTLEFS_VER="v2.11.2"
|
||||
# CONFIG_PKG_USING_DFS_JFFS2 is not set
|
||||
# CONFIG_PKG_USING_DFS_UFFS is not set
|
||||
# CONFIG_PKG_USING_LWEXT4 is not set
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactName="rtthread" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="${cross_rm} -rf" description="" id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.553091094" name="Debug" parent="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug">
|
||||
<configuration artifactName="rtthread" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="${cross_rm} -rf" description="" id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.553091094" name="Debug" parent="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug" postbuildStep="arm-none-eabi-objcopy -O ihex "rtthread.elf" "${ProjName}.hex"">
|
||||
<folderInfo id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.553091094." name="/" resourcePath="">
|
||||
<toolChain id="ilg.gnuarmeclipse.managedbuild.cross.toolchain.elf.debug.1201710416" name="ARM Cross GCC" superClass="ilg.gnuarmeclipse.managedbuild.cross.toolchain.elf.debug">
|
||||
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.createflash.251260409" name="Create flash image" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.addtools.createflash" useByScannerDiscovery="false" value="true" valueType="boolean"/>
|
||||
@@ -76,13 +76,16 @@
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//cubemx/Inc}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//cubemx}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//packages/cJSON-v1.7.17}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//packages/littlefs-v2.11.2}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//packages/sqlite-v3.19.3}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/dfs/dfs_v1/filesystems/devfs}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/dfs/dfs_v1/filesystems/elmfat}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/dfs/dfs_v1/filesystems/tmpfs}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/dfs/dfs_v1/include}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/drivers/include}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/drivers/spi/sfud/inc}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/drivers/spi}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/fal/inc}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/finsh}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/libc/compilers/common/include}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/libc/compilers/newlib}""/>
|
||||
@@ -191,13 +194,16 @@
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//cubemx/Inc}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//cubemx}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//packages/cJSON-v1.7.17}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//packages/littlefs-v2.11.2}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//packages/sqlite-v3.19.3}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/dfs/dfs_v1/filesystems/devfs}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/dfs/dfs_v1/filesystems/elmfat}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/dfs/dfs_v1/filesystems/tmpfs}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/dfs/dfs_v1/include}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/drivers/include}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/drivers/spi/sfud/inc}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/drivers/spi}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/fal/inc}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/finsh}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/libc/compilers/common/include}""/>
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc://${ProjName}//rt-thread/components/libc/compilers/newlib}""/>
|
||||
@@ -217,11 +223,12 @@
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<sourceEntries>
|
||||
<entry excluding="packages/sqlite-v3.19.3/rtthread_vfs.c|//cubemx/Drivers|//cubemx/EWARM|//cubemx/Src/stm32h7xx_it.c|//cubemx/Src/system_stm32h7xx.c|//packages/sqlite-v3.19.3/dbhelper.c|//packages/sqlite-v3.19.3/rtthread_io_methods.c|//packages/sqlite-v3.19.3/rtthread_mutex.c|//packages/sqlite-v3.19.3/rtthread_vfs.c|//packages/sqlite-v3.19.3/shell.c|//packages/sqlite-v3.19.3/student_dao.c|//rt-thread/components/dfs/dfs_v1/filesystems/cromfs|//rt-thread/components/dfs/dfs_v1/filesystems/mqueue|//rt-thread/components/dfs/dfs_v1/filesystems/nfs|//rt-thread/components/dfs/dfs_v1/filesystems/ramfs|//rt-thread/components/dfs/dfs_v1/filesystems/romfs|//rt-thread/components/dfs/dfs_v1/filesystems/skeleton|//rt-thread/components/dfs/dfs_v2|//rt-thread/components/drivers/audio|//rt-thread/components/drivers/can|//rt-thread/components/drivers/clk|//rt-thread/components/drivers/core/dm.c|//rt-thread/components/drivers/core/driver.c|//rt-thread/components/drivers/core/platform.c|//rt-thread/components/drivers/core/platform_ofw.c|//rt-thread/components/drivers/cputime|//rt-thread/components/drivers/fdt|//rt-thread/components/drivers/hwcrypto|//rt-thread/components/drivers/hwtimer|//rt-thread/components/drivers/i2c|//rt-thread/components/drivers/ktime|//rt-thread/components/drivers/misc|//rt-thread/components/drivers/mtd|//rt-thread/components/drivers/ofw|//rt-thread/components/drivers/phy|//rt-thread/components/drivers/pic|//rt-thread/components/drivers/pin/pin_dm.c|//rt-thread/components/drivers/pin/pin_ofw.c|//rt-thread/components/drivers/pinctrl|//rt-thread/components/drivers/pm|//rt-thread/components/drivers/rtc/alarm.c|//rt-thread/components/drivers/sensor|//rt-thread/components/drivers/serial/serial_dm.c|//rt-thread/components/drivers/serial/serial_tty.c|//rt-thread/components/drivers/serial/serial_v2.c|//rt-thread/components/drivers/spi/enc28j60.c|//rt-thread/components/drivers/spi/sfud|//rt-thread/components/drivers/spi/spi-bit-ops.c|//rt-thread/components/drivers/spi/spi_flash_sfud.c|//rt-thread/components/drivers/spi/spi_wifi_rw009.c|//rt-thread/components/drivers/touch|//rt-thread/components/drivers/usb|//rt-thread/components/drivers/virtio|//rt-thread/components/drivers/watchdog|//rt-thread/components/drivers/wlan|//rt-thread/components/fal|//rt-thread/components/legacy|//rt-thread/components/libc/compilers/armlibc|//rt-thread/components/libc/compilers/dlib|//rt-thread/components/libc/compilers/musl|//rt-thread/components/libc/compilers/picolibc|//rt-thread/components/libc/cplusplus|//rt-thread/components/libc/posix|//rt-thread/components/lwp|//rt-thread/components/mm|//rt-thread/components/mprotect|//rt-thread/components/net|//rt-thread/components/utilities|//rt-thread/components/vbus|//rt-thread/libcpu/aarch64|//rt-thread/libcpu/arc|//rt-thread/libcpu/arm/AT91SAM7S|//rt-thread/libcpu/arm/AT91SAM7X|//rt-thread/libcpu/arm/am335x|//rt-thread/libcpu/arm/arm926|//rt-thread/libcpu/arm/armv6|//rt-thread/libcpu/arm/common/atomic_arm.c|//rt-thread/libcpu/arm/common/divsi3.S|//rt-thread/libcpu/arm/cortex-a|//rt-thread/libcpu/arm/cortex-m0|//rt-thread/libcpu/arm/cortex-m23|//rt-thread/libcpu/arm/cortex-m3|//rt-thread/libcpu/arm/cortex-m33|//rt-thread/libcpu/arm/cortex-m4|//rt-thread/libcpu/arm/cortex-m7/context_iar.S|//rt-thread/libcpu/arm/cortex-m7/context_rvds.S|//rt-thread/libcpu/arm/cortex-m7/mpu.c|//rt-thread/libcpu/arm/cortex-m85|//rt-thread/libcpu/arm/cortex-r4|//rt-thread/libcpu/arm/cortex-r52|//rt-thread/libcpu/arm/dm36x|//rt-thread/libcpu/arm/lpc214x|//rt-thread/libcpu/arm/lpc24xx|//rt-thread/libcpu/arm/realview-a8-vmm|//rt-thread/libcpu/arm/s3c24x0|//rt-thread/libcpu/arm/s3c44b0|//rt-thread/libcpu/arm/sep4020|//rt-thread/libcpu/arm/zynqmp-r5|//rt-thread/libcpu/avr32|//rt-thread/libcpu/blackfin|//rt-thread/libcpu/c-sky|//rt-thread/libcpu/ia32|//rt-thread/libcpu/m16c|//rt-thread/libcpu/mips|//rt-thread/libcpu/nios|//rt-thread/libcpu/ppc|//rt-thread/libcpu/risc-v|//rt-thread/libcpu/rx|//rt-thread/libcpu/sim|//rt-thread/libcpu/sparc-v8|//rt-thread/libcpu/ti-dsp|//rt-thread/libcpu/unicore32|//rt-thread/libcpu/v850|//rt-thread/libcpu/xilinx|//rt-thread/src/cpu.c|//rt-thread/src/mem.c|//rt-thread/src/scheduler_mp.c|//rt-thread/src/signal.c|//rt-thread/src/slab.c|//rt-thread/tools" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="" />
|
||||
<entry excluding="packages/sqlite-v3.19.3/rtthread_vfs.c|//cubemx/Drivers|//cubemx/EWARM|//cubemx/Src/stm32h7xx_it.c|//cubemx/Src/system_stm32h7xx.c|//packages/littlefs-v2.11.2/runners|//packages/sqlite-v3.19.3/dbhelper.c|//packages/sqlite-v3.19.3/rtthread_io_methods.c|//packages/sqlite-v3.19.3/rtthread_mutex.c|//packages/sqlite-v3.19.3/rtthread_vfs.c|//packages/sqlite-v3.19.3/shell.c|//packages/sqlite-v3.19.3/student_dao.c|//rt-thread/components/dfs/dfs_v1/filesystems/cromfs|//rt-thread/components/dfs/dfs_v1/filesystems/mqueue|//rt-thread/components/dfs/dfs_v1/filesystems/nfs|//rt-thread/components/dfs/dfs_v1/filesystems/ramfs|//rt-thread/components/dfs/dfs_v1/filesystems/romfs|//rt-thread/components/dfs/dfs_v1/filesystems/skeleton|//rt-thread/components/dfs/dfs_v2|//rt-thread/components/drivers/audio|//rt-thread/components/drivers/can|//rt-thread/components/drivers/clk|//rt-thread/components/drivers/core/dm.c|//rt-thread/components/drivers/core/driver.c|//rt-thread/components/drivers/core/platform.c|//rt-thread/components/drivers/core/platform_ofw.c|//rt-thread/components/drivers/cputime|//rt-thread/components/drivers/fdt|//rt-thread/components/drivers/hwcrypto|//rt-thread/components/drivers/hwtimer|//rt-thread/components/drivers/i2c|//rt-thread/components/drivers/ktime|//rt-thread/components/drivers/misc|//rt-thread/components/drivers/mtd/mtd_nand.c|//rt-thread/components/drivers/ofw|//rt-thread/components/drivers/phy|//rt-thread/components/drivers/pic|//rt-thread/components/drivers/pin/pin_dm.c|//rt-thread/components/drivers/pin/pin_ofw.c|//rt-thread/components/drivers/pinctrl|//rt-thread/components/drivers/pm|//rt-thread/components/drivers/rtc/alarm.c|//rt-thread/components/drivers/sensor|//rt-thread/components/drivers/serial/serial_dm.c|//rt-thread/components/drivers/serial/serial_tty.c|//rt-thread/components/drivers/serial/serial_v2.c|//rt-thread/components/drivers/spi/enc28j60.c|//rt-thread/components/drivers/spi/spi-bit-ops.c|//rt-thread/components/drivers/spi/spi_wifi_rw009.c|//rt-thread/components/drivers/touch|//rt-thread/components/drivers/usb|//rt-thread/components/drivers/virtio|//rt-thread/components/drivers/watchdog|//rt-thread/components/drivers/wlan|//rt-thread/components/fal/samples/porting/fal_flash_stm32f2_port.c|//rt-thread/components/legacy|//rt-thread/components/libc/compilers/armlibc|//rt-thread/components/libc/compilers/dlib|//rt-thread/components/libc/compilers/musl|//rt-thread/components/libc/compilers/picolibc|//rt-thread/components/libc/cplusplus|//rt-thread/components/libc/posix|//rt-thread/components/lwp|//rt-thread/components/mm|//rt-thread/components/mprotect|//rt-thread/components/net|//rt-thread/components/utilities|//rt-thread/components/vbus|//rt-thread/libcpu/aarch64|//rt-thread/libcpu/arc|//rt-thread/libcpu/arm/AT91SAM7S|//rt-thread/libcpu/arm/AT91SAM7X|//rt-thread/libcpu/arm/am335x|//rt-thread/libcpu/arm/arm926|//rt-thread/libcpu/arm/armv6|//rt-thread/libcpu/arm/common/atomic_arm.c|//rt-thread/libcpu/arm/common/divsi3.S|//rt-thread/libcpu/arm/cortex-a|//rt-thread/libcpu/arm/cortex-m0|//rt-thread/libcpu/arm/cortex-m23|//rt-thread/libcpu/arm/cortex-m3|//rt-thread/libcpu/arm/cortex-m33|//rt-thread/libcpu/arm/cortex-m4|//rt-thread/libcpu/arm/cortex-m7/context_iar.S|//rt-thread/libcpu/arm/cortex-m7/context_rvds.S|//rt-thread/libcpu/arm/cortex-m7/mpu.c|//rt-thread/libcpu/arm/cortex-m85|//rt-thread/libcpu/arm/cortex-r4|//rt-thread/libcpu/arm/cortex-r52|//rt-thread/libcpu/arm/dm36x|//rt-thread/libcpu/arm/lpc214x|//rt-thread/libcpu/arm/lpc24xx|//rt-thread/libcpu/arm/realview-a8-vmm|//rt-thread/libcpu/arm/s3c24x0|//rt-thread/libcpu/arm/s3c44b0|//rt-thread/libcpu/arm/sep4020|//rt-thread/libcpu/arm/zynqmp-r5|//rt-thread/libcpu/avr32|//rt-thread/libcpu/blackfin|//rt-thread/libcpu/c-sky|//rt-thread/libcpu/ia32|//rt-thread/libcpu/m16c|//rt-thread/libcpu/mips|//rt-thread/libcpu/nios|//rt-thread/libcpu/ppc|//rt-thread/libcpu/risc-v|//rt-thread/libcpu/rx|//rt-thread/libcpu/sim|//rt-thread/libcpu/sparc-v8|//rt-thread/libcpu/ti-dsp|//rt-thread/libcpu/unicore32|//rt-thread/libcpu/v850|//rt-thread/libcpu/xilinx|//rt-thread/src/cpu.c|//rt-thread/src/mem.c|//rt-thread/src/scheduler_mp.c|//rt-thread/src/signal.c|//rt-thread/src/slab.c|//rt-thread/tools" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||
</sourceEntries>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
<storageModule moduleId="ilg.gnumcueclipse.managedbuild.packs"/>
|
||||
</cconfiguration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
@@ -236,7 +243,7 @@
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
<storageModule moduleId="refreshScope" versionNumber="2">
|
||||
<configuration configurationName="Debug">
|
||||
<resource resourceType="PROJECT" workspacePath="/828F" />
|
||||
<resource resourceType="PROJECT" workspacePath="/project"/>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>828F</name>
|
||||
<name>project</name>
|
||||
<comment />
|
||||
<projects>
|
||||
</projects>
|
||||
|
||||
Binary file not shown.
@@ -5,7 +5,7 @@
|
||||
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
|
||||
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
|
||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-1124315701215259588" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT ARM Cross GCC Built-in Compiler Settings " parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector" console="false" env-hash="-1161191500764276022" id="ilg.gnuarmeclipse.managedbuild.cross.GCCBuiltinSpecsDetector" keep-relative-paths="false" name="CDT ARM Cross GCC Built-in Compiler Settings " parameter="${COMMAND} ${FLAGS} ${cross_toolchain_flags} -E -P -v -dD "${INPUTS}"" prefer-non-shared="true">
|
||||
<language-scope id="org.eclipse.cdt.core.gcc"/>
|
||||
<language-scope id="org.eclipse.cdt.core.g++"/>
|
||||
</provider>
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2025-11-22 Administrator the first version
|
||||
*//*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2025-11-22 Administrator the first version
|
||||
*/
|
||||
#include <rtthread.h>
|
||||
#include <rtdevice.h>
|
||||
#include "fal_cfg.h"
|
||||
#include "spi_flash.h"
|
||||
#include "spi_flash_sfud.h"
|
||||
#include "drv_qspi.h"
|
||||
#include "dfs_fs.h"
|
||||
#include "fal.h"
|
||||
|
||||
/* 添加 DEBUG 头文件 */
|
||||
#include <rtdbg.h>
|
||||
|
||||
char w25qxx_read_status_register2(struct rt_qspi_device *device)
|
||||
{
|
||||
/* 0x35 read status register2 */
|
||||
char instruction = 0x35, status;
|
||||
rt_qspi_send_then_recv(device, &instruction, 1, &status, 1);
|
||||
return status;
|
||||
}
|
||||
|
||||
void w25qxx_write_enable(struct rt_qspi_device *device)
|
||||
{
|
||||
/* 0x06 write enable */
|
||||
char instruction = 0x06;
|
||||
rt_qspi_send(device, &instruction, 1);
|
||||
}
|
||||
|
||||
void w25qxx_enter_qspi_mode(struct rt_qspi_device *device)
|
||||
{
|
||||
char status = 0;
|
||||
/* 0x38 enter qspi mode */
|
||||
char instruction = 0x38;
|
||||
char write_status2_buf[2] = {0};
|
||||
/* 0x31 write status register2 */
|
||||
write_status2_buf[0] = 0x31;
|
||||
status = w25qxx_read_status_register2(device);
|
||||
if (!(status & 0x02))
|
||||
{
|
||||
status |= 1 << 1;
|
||||
w25qxx_write_enable(device);
|
||||
write_status2_buf[1] = status;
|
||||
rt_qspi_send(device, &write_status2_buf, 2);
|
||||
rt_qspi_send(device, &instruction, 1);
|
||||
LOG_D("flash already enter qspi mode");
|
||||
rt_thread_mdelay(10);
|
||||
}
|
||||
}
|
||||
|
||||
int spi_flash_init(void)
|
||||
{
|
||||
rt_err_t ret = stm32_qspi_bus_attach_device("qspi1", "qspi10", RT_NULL, 4, w25qxx_enter_qspi_mode, RT_NULL);
|
||||
if (ret != RT_EOK)
|
||||
{
|
||||
LOG_E("qspi attach device failed\n");
|
||||
return -RT_ERROR;
|
||||
}
|
||||
/* init W25Q256 */
|
||||
// spi_flash_dev_name 需要用配置文件内的,spi_dev_name实际是SPI挂在参数
|
||||
if(rt_sfud_flash_probe(FAL_USING_NOR_FLASH_DEV_NAME, "qspi10") == RT_NULL)
|
||||
{
|
||||
LOG_E("rt sfud flash error");
|
||||
return -1;
|
||||
}
|
||||
LOG_I("SFUD flash '%s' probed successfully.", FAL_USING_NOR_FLASH_DEV_NAME);
|
||||
/* 初始化 fal */
|
||||
int fal_ = fal_init();
|
||||
if (fal_ > 0)
|
||||
{
|
||||
LOG_I("FAL Number of partitions = %d",fal_);
|
||||
}else{
|
||||
return -1;
|
||||
}
|
||||
/* 创建 MTD 块设备 */
|
||||
if (fal_mtd_nor_device_create("sysdata") == RT_NULL)
|
||||
{
|
||||
LOG_E("Failed to create MTD device for sysdata!");
|
||||
return -1;
|
||||
}
|
||||
LOG_I("MTD device 'sysdata' created.");
|
||||
return RT_EOK;
|
||||
}
|
||||
INIT_DEVICE_EXPORT(spi_flash_init);
|
||||
|
||||
int qspi_fal(void)
|
||||
{
|
||||
LOG_I("Create file path /sys");
|
||||
mkdir("/sys", 0777);
|
||||
|
||||
/* 挂载 littlefs */
|
||||
if (dfs_mount("sysdata", "/sys", "lfs", 0, NULL) == RT_EOK)
|
||||
{
|
||||
LOG_I("Filesystem initialized!");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_E("Format memory sysdata");
|
||||
/* 格式化文件系统 */
|
||||
dfs_mkfs("lfs", "sysdata");
|
||||
/* 挂载 littlefs */
|
||||
if (dfs_mount("sysdata", "/sys", "lfs", 0, NULL) == RT_EOK)
|
||||
{
|
||||
LOG_I("Filesystem initialized!");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_E("Failed to initialize filesystem!");
|
||||
}
|
||||
}
|
||||
return RT_EOK;
|
||||
}
|
||||
INIT_APP_EXPORT(qspi_fal);
|
||||
@@ -4,7 +4,7 @@
|
||||
#include"drv_common.h"
|
||||
#include "RUN_LED.h"
|
||||
|
||||
#define LED_PIN GET_PIN(B,0)
|
||||
#define LED_PIN GET_PIN(B,1)
|
||||
|
||||
/* 线程 1 的入口函数 */
|
||||
void RUN_LED(void *parameter)
|
||||
|
||||
@@ -24,6 +24,7 @@ void sd_mount(void *parameter)
|
||||
{
|
||||
if (rt_device_find("sd") != RT_NULL)
|
||||
{
|
||||
LOG_I("Create file path /sddisk");
|
||||
mkdir("/sddisk", 0777);
|
||||
if (dfs_mount("sd", "/sddisk", "elm", 0, NULL) == RT_EOK)
|
||||
{
|
||||
@@ -54,7 +55,6 @@ void sd_mount(void *parameter)
|
||||
int stm32_sdcard_mount(void)
|
||||
{
|
||||
rt_thread_t tid;
|
||||
rt_thread_mdelay(1000);
|
||||
// 删除旧的信号量(如果存在)
|
||||
if (mount_sem != RT_NULL)
|
||||
{
|
||||
@@ -72,7 +72,7 @@ int stm32_sdcard_mount(void)
|
||||
tid = rt_thread_create("sd_mount",
|
||||
sd_mount,
|
||||
RT_NULL,
|
||||
1024*6, // 避免溢出
|
||||
1024*2, // 避免溢出
|
||||
RT_THREAD_PRIORITY_MAX - 2,
|
||||
20);
|
||||
if (tid != RT_NULL)
|
||||
|
||||
@@ -35,4 +35,4 @@ int init_tmpfs_root(void)
|
||||
}
|
||||
|
||||
/* 在应用初始化阶段运行(确保系统已就绪) */
|
||||
INIT_APP_EXPORT(init_tmpfs_root);
|
||||
INIT_DEVICE_EXPORT(init_tmpfs_root);
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2021, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2025-11-22 Administrator the first version
|
||||
*/
|
||||
#ifndef _FAL_CFG_H_
|
||||
#define _FAL_CFG_H_
|
||||
|
||||
#include <rtconfig.h>
|
||||
#include <fal.h>
|
||||
|
||||
extern struct fal_flash_dev nor_flash0;
|
||||
|
||||
/* flash device table */
|
||||
#define FAL_FLASH_DEV_TABLE \
|
||||
{ \
|
||||
&nor_flash0, \
|
||||
}
|
||||
|
||||
/* 分区表:根据你的需求划分 */
|
||||
#define FAL_PART_TABLE \
|
||||
{ \
|
||||
{FAL_PART_MAGIC_WORD, "sysdata","W25Q128", 0, 16 * 1024 * 1024, 0 }, \
|
||||
}
|
||||
|
||||
#endif /* _FAL_CFG_H_ */
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
[PreviousLibFiles]
|
||||
LibFiles=Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_cortex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_cortex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_fmc.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_nor.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_sram.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_nand.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_sdram.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_rcc.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_rcc_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_bus.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_rcc.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_crs.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_system.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_utils.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_flash.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_flash_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_gpio.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_gpio_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_gpio.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_hsem.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_hsem.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_dma.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_dma_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_dma.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_dmamux.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_mdma.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_pwr.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_pwr_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_pwr.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_def.h;Drivers\STM32H7xx_HAL_Driver\Inc\Legacy\stm32_hal_legacy.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_i2c.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_i2c_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_exti.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_exti.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_sdmmc.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_sd.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_delayblock.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_sd_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_mmc.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_mmc_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_tim.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_tim_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_uart.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_usart.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_lpuart.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_uart_ex.h;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_cortex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_fmc.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_nor.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sram.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_nand.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sdram.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_gpio.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_hsem.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mdma.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_exti.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_sdmmc.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_delayblock.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sd.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sd_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mmc.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mmc_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart_ex.c;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_cortex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_cortex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_fmc.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_nor.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_sram.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_nand.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_sdram.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_rcc.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_rcc_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_bus.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_rcc.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_crs.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_system.h;DLine truncated
|
||||
LibFiles=Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_cortex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_cortex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_fmc.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_nor.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_sram.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_nand.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_sdram.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_rcc.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_rcc_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_bus.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_rcc.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_crs.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_system.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_utils.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_flash.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_flash_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_gpio.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_gpio_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_gpio.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_hsem.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_hsem.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_dma.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_dma_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_dma.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_dmamux.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_mdma.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_pwr.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_pwr_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_pwr.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_def.h;Drivers\STM32H7xx_HAL_Driver\Inc\Legacy\stm32_hal_legacy.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_i2c.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_i2c_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_exti.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_exti.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_qspi.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_delayblock.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_sdmmc.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_sd.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_sd_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_mmc.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_mmc_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_tim.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_tim_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_uart.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_usart.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_lpuart.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_uart_ex.h;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_cortex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_fmc.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_nor.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sram.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_nand.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sdram.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_gpio.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_hsem.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mdma.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_exti.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_qspi.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_delayblock.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_sdmmc.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sd.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sd_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mmc.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mmc_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim_ex.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart.c;Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart_ex.c;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_cortex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_cortex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_fmc.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_nor.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_sram.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_nand.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_sdram.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_rcc.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_hal_rcc_ex.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_bus.h;Drivers\STM32H7xx_HAL_Driver\Inc\stm32h7xx_ll_rcc.h;Line truncated
|
||||
|
||||
[PreviousUsedIarFiles]
|
||||
SourceFiles=..\Src\main.c;..\Src\stm32h7xx_it.c;..\Src\stm32h7xx_hal_msp.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_cortex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_fmc.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_nor.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sram.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_nand.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sdram.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_gpio.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_hsem.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mdma.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_exti.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_sdmmc.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_delayblock.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sd.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sd_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mmc.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mmc_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart_ex.c;..\Drivers\CMSIS\Device\ST\STM32H7xx\Source\Templates\system_stm32h7xx.c;..\\Src\system_stm32h7xx.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_cortex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_fmc.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_nor.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sram.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_nand.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sdram.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_gpio.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_hsem.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mdma.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_exti.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_sdmmc.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_delayblock.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sd.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sd_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mmc.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mmc_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart_ex.c;..\Drivers\CMSIS\Device\ST\STM32H7xx\Source\Templates\system_stm32h7xx.c;..\\Src\system_stm32h7xx.c;;;
|
||||
SourceFiles=..\Src\main.c;..\Src\stm32h7xx_it.c;..\Src\stm32h7xx_hal_msp.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_cortex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_fmc.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_nor.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sram.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_nand.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sdram.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_gpio.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_hsem.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mdma.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_exti.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_qspi.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_delayblock.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_sdmmc.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sd.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sd_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mmc.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mmc_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart_ex.c;..\Drivers\CMSIS\Device\ST\STM32H7xx\Source\Templates\system_stm32h7xx.c;..\\Src\system_stm32h7xx.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_cortex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_fmc.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_nor.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sram.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_nand.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sdram.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_rcc_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_flash_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_gpio.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_hsem.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_dma_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mdma.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_pwr_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_i2c_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_exti.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_qspi.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_delayblock.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_ll_sdmmc.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sd.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_sd_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mmc.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_mmc_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_tim_ex.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart.c;..\Drivers\STM32H7xx_HAL_Driver\Src\stm32h7xx_hal_uart_ex.c;..\Drivers\CMSIS\Device\ST\STM32H7xx\Source\Templates\system_stm32h7xx.c;..\\Src\system_stm32h7xx.c;;;
|
||||
HeaderPath=..\Drivers\STM32H7xx_HAL_Driver\Inc;..\Drivers\STM32H7xx_HAL_Driver\Inc\Legacy;..\Drivers\CMSIS\Device\ST\STM32H7xx\Include;..\Drivers\CMSIS\Include;..\Inc;
|
||||
CDefines=USE_PWR_LDO_SUPPLY;USE_HAL_DRIVER;STM32H743xx;USE_HAL_DRIVER;USE_HAL_DRIVER;
|
||||
|
||||
|
||||
@@ -0,0 +1,747 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32h7xx_hal_qspi.h
|
||||
* @author MCD Application Team
|
||||
* @brief Header file of QSPI HAL module.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2017 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef STM32H7xx_HAL_QSPI_H
|
||||
#define STM32H7xx_HAL_QSPI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32h7xx_hal_def.h"
|
||||
#if defined (DLYB_QUADSPI)
|
||||
#include "stm32h7xx_ll_delayblock.h"
|
||||
#endif /* DLYB_QUADSPI */
|
||||
|
||||
#if defined(QUADSPI)
|
||||
|
||||
/** @addtogroup STM32H7xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup QSPI
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/** @defgroup QSPI_Exported_Types QSPI Exported Types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief QSPI Init structure definition
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t ClockPrescaler; /* Specifies the prescaler factor for generating clock based on the AHB clock.
|
||||
This parameter can be a number between 0 and 255 */
|
||||
uint32_t FifoThreshold; /* Specifies the threshold number of bytes in the FIFO (used only in indirect mode)
|
||||
This parameter can be a value between 1 and 32 */
|
||||
uint32_t SampleShifting; /* Specifies the Sample Shift. The data is sampled 1/2 clock cycle delay later to
|
||||
take in account external signal delays. (It should be QSPI_SAMPLE_SHIFTING_NONE in DDR mode)
|
||||
This parameter can be a value of @ref QSPI_SampleShifting */
|
||||
uint32_t FlashSize; /* Specifies the Flash Size. FlashSize+1 is effectively the number of address bits
|
||||
required to address the flash memory. The flash capacity can be up to 4GB
|
||||
(addressed using 32 bits) in indirect mode, but the addressable space in
|
||||
memory-mapped mode is limited to 256MB
|
||||
This parameter can be a number between 0 and 31 */
|
||||
uint32_t ChipSelectHighTime; /* Specifies the Chip Select High Time. ChipSelectHighTime+1 defines the minimum number
|
||||
of clock cycles which the chip select must remain high between commands.
|
||||
This parameter can be a value of @ref QSPI_ChipSelectHighTime */
|
||||
uint32_t ClockMode; /* Specifies the Clock Mode. It indicates the level that clock takes between commands.
|
||||
This parameter can be a value of @ref QSPI_ClockMode */
|
||||
uint32_t FlashID; /* Specifies the Flash which will be used,
|
||||
This parameter can be a value of @ref QSPI_Flash_Select */
|
||||
uint32_t DualFlash; /* Specifies the Dual Flash Mode State
|
||||
This parameter can be a value of @ref QSPI_DualFlash_Mode */
|
||||
}QSPI_InitTypeDef;
|
||||
|
||||
/**
|
||||
* @brief HAL QSPI State structures definition
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
HAL_QSPI_STATE_RESET = 0x00U, /*!< Peripheral not initialized */
|
||||
HAL_QSPI_STATE_READY = 0x01U, /*!< Peripheral initialized and ready for use */
|
||||
HAL_QSPI_STATE_BUSY = 0x02U, /*!< Peripheral in indirect mode and busy */
|
||||
HAL_QSPI_STATE_BUSY_INDIRECT_TX = 0x12U, /*!< Peripheral in indirect mode with transmission ongoing */
|
||||
HAL_QSPI_STATE_BUSY_INDIRECT_RX = 0x22U, /*!< Peripheral in indirect mode with reception ongoing */
|
||||
HAL_QSPI_STATE_BUSY_AUTO_POLLING = 0x42U, /*!< Peripheral in auto polling mode ongoing */
|
||||
HAL_QSPI_STATE_BUSY_MEM_MAPPED = 0x82U, /*!< Peripheral in memory mapped mode ongoing */
|
||||
HAL_QSPI_STATE_ABORT = 0x08U, /*!< Peripheral with abort request ongoing */
|
||||
HAL_QSPI_STATE_ERROR = 0x04U /*!< Peripheral in error */
|
||||
}HAL_QSPI_StateTypeDef;
|
||||
|
||||
/**
|
||||
* @brief QSPI Handle Structure definition
|
||||
*/
|
||||
#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
|
||||
typedef struct __QSPI_HandleTypeDef
|
||||
#else
|
||||
typedef struct
|
||||
#endif
|
||||
{
|
||||
QUADSPI_TypeDef *Instance; /* QSPI registers base address */
|
||||
QSPI_InitTypeDef Init; /* QSPI communication parameters */
|
||||
uint8_t *pTxBuffPtr; /* Pointer to QSPI Tx transfer Buffer */
|
||||
__IO uint32_t TxXferSize; /* QSPI Tx Transfer size */
|
||||
__IO uint32_t TxXferCount; /* QSPI Tx Transfer Counter */
|
||||
uint8_t *pRxBuffPtr; /* Pointer to QSPI Rx transfer Buffer */
|
||||
__IO uint32_t RxXferSize; /* QSPI Rx Transfer size */
|
||||
__IO uint32_t RxXferCount; /* QSPI Rx Transfer Counter */
|
||||
MDMA_HandleTypeDef *hmdma; /* QSPI Rx/Tx MDMA Handle parameters */
|
||||
__IO HAL_LockTypeDef Lock; /* Locking object */
|
||||
__IO HAL_QSPI_StateTypeDef State; /* QSPI communication state */
|
||||
__IO uint32_t ErrorCode; /* QSPI Error code */
|
||||
uint32_t Timeout; /* Timeout for the QSPI memory access */
|
||||
#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
|
||||
void (* ErrorCallback) (struct __QSPI_HandleTypeDef *hqspi);
|
||||
void (* AbortCpltCallback) (struct __QSPI_HandleTypeDef *hqspi);
|
||||
void (* FifoThresholdCallback)(struct __QSPI_HandleTypeDef *hqspi);
|
||||
void (* CmdCpltCallback) (struct __QSPI_HandleTypeDef *hqspi);
|
||||
void (* RxCpltCallback) (struct __QSPI_HandleTypeDef *hqspi);
|
||||
void (* TxCpltCallback) (struct __QSPI_HandleTypeDef *hqspi);
|
||||
void (* StatusMatchCallback) (struct __QSPI_HandleTypeDef *hqspi);
|
||||
void (* TimeOutCallback) (struct __QSPI_HandleTypeDef *hqspi);
|
||||
|
||||
void (* MspInitCallback) (struct __QSPI_HandleTypeDef *hqspi);
|
||||
void (* MspDeInitCallback) (struct __QSPI_HandleTypeDef *hqspi);
|
||||
#endif
|
||||
}QSPI_HandleTypeDef;
|
||||
|
||||
/**
|
||||
* @brief QSPI Command structure definition
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t Instruction; /* Specifies the Instruction to be sent
|
||||
This parameter can be a value (8-bit) between 0x00 and 0xFF */
|
||||
uint32_t Address; /* Specifies the Address to be sent (Size from 1 to 4 bytes according AddressSize)
|
||||
This parameter can be a value (32-bits) between 0x0 and 0xFFFFFFFF */
|
||||
uint32_t AlternateBytes; /* Specifies the Alternate Bytes to be sent (Size from 1 to 4 bytes according AlternateBytesSize)
|
||||
This parameter can be a value (32-bits) between 0x0 and 0xFFFFFFFF */
|
||||
uint32_t AddressSize; /* Specifies the Address Size
|
||||
This parameter can be a value of @ref QSPI_AddressSize */
|
||||
uint32_t AlternateBytesSize; /* Specifies the Alternate Bytes Size
|
||||
This parameter can be a value of @ref QSPI_AlternateBytesSize */
|
||||
uint32_t DummyCycles; /* Specifies the Number of Dummy Cycles.
|
||||
This parameter can be a number between 0 and 31 */
|
||||
uint32_t InstructionMode; /* Specifies the Instruction Mode
|
||||
This parameter can be a value of @ref QSPI_InstructionMode */
|
||||
uint32_t AddressMode; /* Specifies the Address Mode
|
||||
This parameter can be a value of @ref QSPI_AddressMode */
|
||||
uint32_t AlternateByteMode; /* Specifies the Alternate Bytes Mode
|
||||
This parameter can be a value of @ref QSPI_AlternateBytesMode */
|
||||
uint32_t DataMode; /* Specifies the Data Mode (used for dummy cycles and data phases)
|
||||
This parameter can be a value of @ref QSPI_DataMode */
|
||||
uint32_t NbData; /* Specifies the number of data to transfer. (This is the number of bytes)
|
||||
This parameter can be any value between 0 and 0xFFFFFFFF (0 means undefined length
|
||||
until end of memory)*/
|
||||
uint32_t DdrMode; /* Specifies the double data rate mode for address, alternate byte and data phase
|
||||
This parameter can be a value of @ref QSPI_DdrMode */
|
||||
uint32_t DdrHoldHalfCycle; /* Specifies if the DDR hold is enabled. When enabled it delays the data
|
||||
output by one half of system clock in DDR mode.
|
||||
This parameter can be a value of @ref QSPI_DdrHoldHalfCycle */
|
||||
uint32_t SIOOMode; /* Specifies the send instruction only once mode
|
||||
This parameter can be a value of @ref QSPI_SIOOMode */
|
||||
}QSPI_CommandTypeDef;
|
||||
|
||||
/**
|
||||
* @brief QSPI Auto Polling mode configuration structure definition
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t Match; /* Specifies the value to be compared with the masked status register to get a match.
|
||||
This parameter can be any value between 0 and 0xFFFFFFFF */
|
||||
uint32_t Mask; /* Specifies the mask to be applied to the status bytes received.
|
||||
This parameter can be any value between 0 and 0xFFFFFFFF */
|
||||
uint32_t Interval; /* Specifies the number of clock cycles between two read during automatic polling phases.
|
||||
This parameter can be any value between 0 and 0xFFFF */
|
||||
uint32_t StatusBytesSize; /* Specifies the size of the status bytes received.
|
||||
This parameter can be any value between 1 and 4 */
|
||||
uint32_t MatchMode; /* Specifies the method used for determining a match.
|
||||
This parameter can be a value of @ref QSPI_MatchMode */
|
||||
uint32_t AutomaticStop; /* Specifies if automatic polling is stopped after a match.
|
||||
This parameter can be a value of @ref QSPI_AutomaticStop */
|
||||
}QSPI_AutoPollingTypeDef;
|
||||
|
||||
/**
|
||||
* @brief QSPI Memory Mapped mode configuration structure definition
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t TimeOutPeriod; /* Specifies the number of clock to wait when the FIFO is full before to release the chip select.
|
||||
This parameter can be any value between 0 and 0xFFFF */
|
||||
uint32_t TimeOutActivation; /* Specifies if the timeout counter is enabled to release the chip select.
|
||||
This parameter can be a value of @ref QSPI_TimeOutActivation */
|
||||
}QSPI_MemoryMappedTypeDef;
|
||||
|
||||
#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief HAL QSPI Callback ID enumeration definition
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
HAL_QSPI_ERROR_CB_ID = 0x00U, /*!< QSPI Error Callback ID */
|
||||
HAL_QSPI_ABORT_CB_ID = 0x01U, /*!< QSPI Abort Callback ID */
|
||||
HAL_QSPI_FIFO_THRESHOLD_CB_ID = 0x02U, /*!< QSPI FIFO Threshold Callback ID */
|
||||
HAL_QSPI_CMD_CPLT_CB_ID = 0x03U, /*!< QSPI Command Complete Callback ID */
|
||||
HAL_QSPI_RX_CPLT_CB_ID = 0x04U, /*!< QSPI Rx Complete Callback ID */
|
||||
HAL_QSPI_TX_CPLT_CB_ID = 0x05U, /*!< QSPI Tx Complete Callback ID */
|
||||
HAL_QSPI_STATUS_MATCH_CB_ID = 0x08U, /*!< QSPI Status Match Callback ID */
|
||||
HAL_QSPI_TIMEOUT_CB_ID = 0x09U, /*!< QSPI Timeout Callback ID */
|
||||
|
||||
HAL_QSPI_MSP_INIT_CB_ID = 0x0AU, /*!< QSPI MspInit Callback ID */
|
||||
HAL_QSPI_MSP_DEINIT_CB_ID = 0x0B0 /*!< QSPI MspDeInit Callback ID */
|
||||
}HAL_QSPI_CallbackIDTypeDef;
|
||||
|
||||
/**
|
||||
* @brief HAL QSPI Callback pointer definition
|
||||
*/
|
||||
typedef void (*pQSPI_CallbackTypeDef)(QSPI_HandleTypeDef *hqspi);
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/** @defgroup QSPI_Exported_Constants QSPI Exported Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_ErrorCode QSPI Error Code
|
||||
* @{
|
||||
*/
|
||||
#define HAL_QSPI_ERROR_NONE 0x00000000U /*!< No error */
|
||||
#define HAL_QSPI_ERROR_TIMEOUT 0x00000001U /*!< Timeout error */
|
||||
#define HAL_QSPI_ERROR_TRANSFER 0x00000002U /*!< Transfer error */
|
||||
#define HAL_QSPI_ERROR_DMA 0x00000004U /*!< DMA transfer error */
|
||||
#define HAL_QSPI_ERROR_INVALID_PARAM 0x00000008U /*!< Invalid parameters error */
|
||||
#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
|
||||
#define HAL_QSPI_ERROR_INVALID_CALLBACK 0x00000010U /*!< Invalid callback error */
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_SampleShifting QSPI Sample Shifting
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_SAMPLE_SHIFTING_NONE 0x00000000U /*!<No clock cycle shift to sample data*/
|
||||
#define QSPI_SAMPLE_SHIFTING_HALFCYCLE ((uint32_t)QUADSPI_CR_SSHIFT) /*!<1/2 clock cycle shift to sample data*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_ChipSelectHighTime QSPI ChipSelect High Time
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_CS_HIGH_TIME_1_CYCLE 0x00000000U /*!<nCS stay high for at least 1 clock cycle between commands*/
|
||||
#define QSPI_CS_HIGH_TIME_2_CYCLE ((uint32_t)QUADSPI_DCR_CSHT_0) /*!<nCS stay high for at least 2 clock cycles between commands*/
|
||||
#define QSPI_CS_HIGH_TIME_3_CYCLE ((uint32_t)QUADSPI_DCR_CSHT_1) /*!<nCS stay high for at least 3 clock cycles between commands*/
|
||||
#define QSPI_CS_HIGH_TIME_4_CYCLE ((uint32_t)QUADSPI_DCR_CSHT_0 | QUADSPI_DCR_CSHT_1) /*!<nCS stay high for at least 4 clock cycles between commands*/
|
||||
#define QSPI_CS_HIGH_TIME_5_CYCLE ((uint32_t)QUADSPI_DCR_CSHT_2) /*!<nCS stay high for at least 5 clock cycles between commands*/
|
||||
#define QSPI_CS_HIGH_TIME_6_CYCLE ((uint32_t)QUADSPI_DCR_CSHT_2 | QUADSPI_DCR_CSHT_0) /*!<nCS stay high for at least 6 clock cycles between commands*/
|
||||
#define QSPI_CS_HIGH_TIME_7_CYCLE ((uint32_t)QUADSPI_DCR_CSHT_2 | QUADSPI_DCR_CSHT_1) /*!<nCS stay high for at least 7 clock cycles between commands*/
|
||||
#define QSPI_CS_HIGH_TIME_8_CYCLE ((uint32_t)QUADSPI_DCR_CSHT) /*!<nCS stay high for at least 8 clock cycles between commands*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_ClockMode QSPI Clock Mode
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_CLOCK_MODE_0 0x00000000U /*!<Clk stays low while nCS is released*/
|
||||
#define QSPI_CLOCK_MODE_3 ((uint32_t)QUADSPI_DCR_CKMODE) /*!<Clk goes high while nCS is released*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_Flash_Select QSPI Flash Select
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_FLASH_ID_1 0x00000000U /*!<FLASH 1 selected*/
|
||||
#define QSPI_FLASH_ID_2 ((uint32_t)QUADSPI_CR_FSEL) /*!<FLASH 2 selected*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_DualFlash_Mode QSPI Dual Flash Mode
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_DUALFLASH_ENABLE ((uint32_t)QUADSPI_CR_DFM) /*!<Dual-flash mode enabled*/
|
||||
#define QSPI_DUALFLASH_DISABLE 0x00000000U /*!<Dual-flash mode disabled*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_AddressSize QSPI Address Size
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_ADDRESS_8_BITS 0x00000000U /*!<8-bit address*/
|
||||
#define QSPI_ADDRESS_16_BITS ((uint32_t)QUADSPI_CCR_ADSIZE_0) /*!<16-bit address*/
|
||||
#define QSPI_ADDRESS_24_BITS ((uint32_t)QUADSPI_CCR_ADSIZE_1) /*!<24-bit address*/
|
||||
#define QSPI_ADDRESS_32_BITS ((uint32_t)QUADSPI_CCR_ADSIZE) /*!<32-bit address*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_AlternateBytesSize QSPI Alternate Bytes Size
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_ALTERNATE_BYTES_8_BITS 0x00000000U /*!<8-bit alternate bytes*/
|
||||
#define QSPI_ALTERNATE_BYTES_16_BITS ((uint32_t)QUADSPI_CCR_ABSIZE_0) /*!<16-bit alternate bytes*/
|
||||
#define QSPI_ALTERNATE_BYTES_24_BITS ((uint32_t)QUADSPI_CCR_ABSIZE_1) /*!<24-bit alternate bytes*/
|
||||
#define QSPI_ALTERNATE_BYTES_32_BITS ((uint32_t)QUADSPI_CCR_ABSIZE) /*!<32-bit alternate bytes*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_InstructionMode QSPI Instruction Mode
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_INSTRUCTION_NONE 0x00000000U /*!<No instruction*/
|
||||
#define QSPI_INSTRUCTION_1_LINE ((uint32_t)QUADSPI_CCR_IMODE_0) /*!<Instruction on a single line*/
|
||||
#define QSPI_INSTRUCTION_2_LINES ((uint32_t)QUADSPI_CCR_IMODE_1) /*!<Instruction on two lines*/
|
||||
#define QSPI_INSTRUCTION_4_LINES ((uint32_t)QUADSPI_CCR_IMODE) /*!<Instruction on four lines*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_AddressMode QSPI Address Mode
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_ADDRESS_NONE 0x00000000U /*!<No address*/
|
||||
#define QSPI_ADDRESS_1_LINE ((uint32_t)QUADSPI_CCR_ADMODE_0) /*!<Address on a single line*/
|
||||
#define QSPI_ADDRESS_2_LINES ((uint32_t)QUADSPI_CCR_ADMODE_1) /*!<Address on two lines*/
|
||||
#define QSPI_ADDRESS_4_LINES ((uint32_t)QUADSPI_CCR_ADMODE) /*!<Address on four lines*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_AlternateBytesMode QSPI Alternate Bytes Mode
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_ALTERNATE_BYTES_NONE 0x00000000U /*!<No alternate bytes*/
|
||||
#define QSPI_ALTERNATE_BYTES_1_LINE ((uint32_t)QUADSPI_CCR_ABMODE_0) /*!<Alternate bytes on a single line*/
|
||||
#define QSPI_ALTERNATE_BYTES_2_LINES ((uint32_t)QUADSPI_CCR_ABMODE_1) /*!<Alternate bytes on two lines*/
|
||||
#define QSPI_ALTERNATE_BYTES_4_LINES ((uint32_t)QUADSPI_CCR_ABMODE) /*!<Alternate bytes on four lines*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_DataMode QSPI Data Mode
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_DATA_NONE 0x00000000U /*!<No data*/
|
||||
#define QSPI_DATA_1_LINE ((uint32_t)QUADSPI_CCR_DMODE_0) /*!<Data on a single line*/
|
||||
#define QSPI_DATA_2_LINES ((uint32_t)QUADSPI_CCR_DMODE_1) /*!<Data on two lines*/
|
||||
#define QSPI_DATA_4_LINES ((uint32_t)QUADSPI_CCR_DMODE) /*!<Data on four lines*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_DdrMode QSPI DDR Mode
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_DDR_MODE_DISABLE 0x00000000U /*!<Double data rate mode disabled*/
|
||||
#define QSPI_DDR_MODE_ENABLE ((uint32_t)QUADSPI_CCR_DDRM) /*!<Double data rate mode enabled*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_DdrHoldHalfCycle QSPI DDR Data Output Delay
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_DDR_HHC_ANALOG_DELAY 0x00000000U /*!<Delay the data output using analog delay in DDR mode*/
|
||||
#define QSPI_DDR_HHC_HALF_CLK_DELAY ((uint32_t)QUADSPI_CCR_DHHC) /*!<Delay the data output by one half of system clock in DDR mode*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_SIOOMode QSPI Send Instruction Mode
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_SIOO_INST_EVERY_CMD 0x00000000U /*!<Send instruction on every transaction*/
|
||||
#define QSPI_SIOO_INST_ONLY_FIRST_CMD ((uint32_t)QUADSPI_CCR_SIOO) /*!<Send instruction only for the first command*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_MatchMode QSPI Match Mode
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_MATCH_MODE_AND 0x00000000U /*!<AND match mode between unmasked bits*/
|
||||
#define QSPI_MATCH_MODE_OR ((uint32_t)QUADSPI_CR_PMM) /*!<OR match mode between unmasked bits*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_AutomaticStop QSPI Automatic Stop
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_AUTOMATIC_STOP_DISABLE 0x00000000U /*!<AutoPolling stops only with abort or QSPI disabling*/
|
||||
#define QSPI_AUTOMATIC_STOP_ENABLE ((uint32_t)QUADSPI_CR_APMS) /*!<AutoPolling stops as soon as there is a match*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_TimeOutActivation QSPI Timeout Activation
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_TIMEOUT_COUNTER_DISABLE 0x00000000U /*!<Timeout counter disabled, nCS remains active*/
|
||||
#define QSPI_TIMEOUT_COUNTER_ENABLE ((uint32_t)QUADSPI_CR_TCEN) /*!<Timeout counter enabled, nCS released when timeout expires*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_Flags QSPI Flags
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_FLAG_BUSY QUADSPI_SR_BUSY /*!<Busy flag: operation is ongoing*/
|
||||
#define QSPI_FLAG_TO QUADSPI_SR_TOF /*!<Timeout flag: timeout occurs in memory-mapped mode*/
|
||||
#define QSPI_FLAG_SM QUADSPI_SR_SMF /*!<Status match flag: received data matches in autopolling mode*/
|
||||
#define QSPI_FLAG_FT QUADSPI_SR_FTF /*!<Fifo threshold flag: Fifo threshold reached or data left after read from memory is complete*/
|
||||
#define QSPI_FLAG_TC QUADSPI_SR_TCF /*!<Transfer complete flag: programmed number of data have been transferred or the transfer has been aborted*/
|
||||
#define QSPI_FLAG_TE QUADSPI_SR_TEF /*!<Transfer error flag: invalid address is being accessed*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_Interrupts QSPI Interrupts
|
||||
* @{
|
||||
*/
|
||||
#define QSPI_IT_TO QUADSPI_CR_TOIE /*!<Interrupt on the timeout flag*/
|
||||
#define QSPI_IT_SM QUADSPI_CR_SMIE /*!<Interrupt on the status match flag*/
|
||||
#define QSPI_IT_FT QUADSPI_CR_FTIE /*!<Interrupt on the fifo threshold flag*/
|
||||
#define QSPI_IT_TC QUADSPI_CR_TCIE /*!<Interrupt on the transfer complete flag*/
|
||||
#define QSPI_IT_TE QUADSPI_CR_TEIE /*!<Interrupt on the transfer error flag*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup QSPI_Timeout_definition QSPI Timeout definition
|
||||
* @brief QSPI Timeout definition
|
||||
* @{
|
||||
*/
|
||||
#define HAL_QSPI_TIMEOUT_DEFAULT_VALUE 5000U /* 5 s */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported macros -----------------------------------------------------------*/
|
||||
/** @defgroup QSPI_Exported_Macros QSPI Exported Macros
|
||||
* @{
|
||||
*/
|
||||
/** @brief Reset QSPI handle state.
|
||||
* @param __HANDLE__ QSPI handle.
|
||||
* @retval None
|
||||
*/
|
||||
#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
|
||||
#define __HAL_QSPI_RESET_HANDLE_STATE(__HANDLE__) do { \
|
||||
(__HANDLE__)->State = HAL_QSPI_STATE_RESET; \
|
||||
(__HANDLE__)->MspInitCallback = NULL; \
|
||||
(__HANDLE__)->MspDeInitCallback = NULL; \
|
||||
} while(0)
|
||||
#else
|
||||
#define __HAL_QSPI_RESET_HANDLE_STATE(__HANDLE__) ((__HANDLE__)->State = HAL_QSPI_STATE_RESET)
|
||||
#endif
|
||||
|
||||
/** @brief Enable the QSPI peripheral.
|
||||
* @param __HANDLE__ specifies the QSPI Handle.
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_QSPI_ENABLE(__HANDLE__) SET_BIT((__HANDLE__)->Instance->CR, QUADSPI_CR_EN)
|
||||
|
||||
/** @brief Disable the QSPI peripheral.
|
||||
* @param __HANDLE__ specifies the QSPI Handle.
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_QSPI_DISABLE(__HANDLE__) CLEAR_BIT((__HANDLE__)->Instance->CR, QUADSPI_CR_EN)
|
||||
|
||||
/** @brief Enable the specified QSPI interrupt.
|
||||
* @param __HANDLE__ specifies the QSPI Handle.
|
||||
* @param __INTERRUPT__ specifies the QSPI interrupt source to enable.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg QSPI_IT_TO: QSPI Timeout interrupt
|
||||
* @arg QSPI_IT_SM: QSPI Status match interrupt
|
||||
* @arg QSPI_IT_FT: QSPI FIFO threshold interrupt
|
||||
* @arg QSPI_IT_TC: QSPI Transfer complete interrupt
|
||||
* @arg QSPI_IT_TE: QSPI Transfer error interrupt
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_QSPI_ENABLE_IT(__HANDLE__, __INTERRUPT__) SET_BIT((__HANDLE__)->Instance->CR, (__INTERRUPT__))
|
||||
|
||||
|
||||
/** @brief Disable the specified QSPI interrupt.
|
||||
* @param __HANDLE__ specifies the QSPI Handle.
|
||||
* @param __INTERRUPT__ specifies the QSPI interrupt source to disable.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg QSPI_IT_TO: QSPI Timeout interrupt
|
||||
* @arg QSPI_IT_SM: QSPI Status match interrupt
|
||||
* @arg QSPI_IT_FT: QSPI FIFO threshold interrupt
|
||||
* @arg QSPI_IT_TC: QSPI Transfer complete interrupt
|
||||
* @arg QSPI_IT_TE: QSPI Transfer error interrupt
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_QSPI_DISABLE_IT(__HANDLE__, __INTERRUPT__) CLEAR_BIT((__HANDLE__)->Instance->CR, (__INTERRUPT__))
|
||||
|
||||
/** @brief Check whether the specified QSPI interrupt source is enabled or not.
|
||||
* @param __HANDLE__ specifies the QSPI Handle.
|
||||
* @param __INTERRUPT__ specifies the QSPI interrupt source to check.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg QSPI_IT_TO: QSPI Timeout interrupt
|
||||
* @arg QSPI_IT_SM: QSPI Status match interrupt
|
||||
* @arg QSPI_IT_FT: QSPI FIFO threshold interrupt
|
||||
* @arg QSPI_IT_TC: QSPI Transfer complete interrupt
|
||||
* @arg QSPI_IT_TE: QSPI Transfer error interrupt
|
||||
* @retval The new state of __INTERRUPT__ (TRUE or FALSE).
|
||||
*/
|
||||
#define __HAL_QSPI_GET_IT_SOURCE(__HANDLE__, __INTERRUPT__) (READ_BIT((__HANDLE__)->Instance->CR, (__INTERRUPT__)) == (__INTERRUPT__))
|
||||
|
||||
/**
|
||||
* @brief Check whether the selected QSPI flag is set or not.
|
||||
* @param __HANDLE__ specifies the QSPI Handle.
|
||||
* @param __FLAG__ specifies the QSPI flag to check.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg QSPI_FLAG_BUSY: QSPI Busy flag
|
||||
* @arg QSPI_FLAG_TO: QSPI Timeout flag
|
||||
* @arg QSPI_FLAG_SM: QSPI Status match flag
|
||||
* @arg QSPI_FLAG_FT: QSPI FIFO threshold flag
|
||||
* @arg QSPI_FLAG_TC: QSPI Transfer complete flag
|
||||
* @arg QSPI_FLAG_TE: QSPI Transfer error flag
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_QSPI_GET_FLAG(__HANDLE__, __FLAG__) ((READ_BIT((__HANDLE__)->Instance->SR, (__FLAG__)) != 0U) ? SET : RESET)
|
||||
|
||||
/** @brief Clears the specified QSPI's flag status.
|
||||
* @param __HANDLE__ specifies the QSPI Handle.
|
||||
* @param __FLAG__ specifies the QSPI clear register flag that needs to be set
|
||||
* This parameter can be one of the following values:
|
||||
* @arg QSPI_FLAG_TO: QSPI Timeout flag
|
||||
* @arg QSPI_FLAG_SM: QSPI Status match flag
|
||||
* @arg QSPI_FLAG_TC: QSPI Transfer complete flag
|
||||
* @arg QSPI_FLAG_TE: QSPI Transfer error flag
|
||||
* @retval None
|
||||
*/
|
||||
#define __HAL_QSPI_CLEAR_FLAG(__HANDLE__, __FLAG__) WRITE_REG((__HANDLE__)->Instance->FCR, (__FLAG__))
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup QSPI_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup QSPI_Exported_Functions_Group1
|
||||
* @{
|
||||
*/
|
||||
/* Initialization/de-initialization functions ********************************/
|
||||
HAL_StatusTypeDef HAL_QSPI_Init (QSPI_HandleTypeDef *hqspi);
|
||||
HAL_StatusTypeDef HAL_QSPI_DeInit (QSPI_HandleTypeDef *hqspi);
|
||||
void HAL_QSPI_MspInit (QSPI_HandleTypeDef *hqspi);
|
||||
void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef *hqspi);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup QSPI_Exported_Functions_Group2
|
||||
* @{
|
||||
*/
|
||||
/* IO operation functions *****************************************************/
|
||||
/* QSPI IRQ handler method */
|
||||
void HAL_QSPI_IRQHandler(QSPI_HandleTypeDef *hqspi);
|
||||
|
||||
/* QSPI indirect mode */
|
||||
HAL_StatusTypeDef HAL_QSPI_Command (QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, uint32_t Timeout);
|
||||
HAL_StatusTypeDef HAL_QSPI_Transmit (QSPI_HandleTypeDef *hqspi, uint8_t *pData, uint32_t Timeout);
|
||||
HAL_StatusTypeDef HAL_QSPI_Receive (QSPI_HandleTypeDef *hqspi, uint8_t *pData, uint32_t Timeout);
|
||||
HAL_StatusTypeDef HAL_QSPI_Command_IT (QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd);
|
||||
HAL_StatusTypeDef HAL_QSPI_Transmit_IT (QSPI_HandleTypeDef *hqspi, uint8_t *pData);
|
||||
HAL_StatusTypeDef HAL_QSPI_Receive_IT (QSPI_HandleTypeDef *hqspi, uint8_t *pData);
|
||||
HAL_StatusTypeDef HAL_QSPI_Transmit_DMA (QSPI_HandleTypeDef *hqspi, uint8_t *pData);
|
||||
HAL_StatusTypeDef HAL_QSPI_Receive_DMA (QSPI_HandleTypeDef *hqspi, uint8_t *pData);
|
||||
|
||||
/* QSPI status flag polling mode */
|
||||
HAL_StatusTypeDef HAL_QSPI_AutoPolling (QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_AutoPollingTypeDef *cfg, uint32_t Timeout);
|
||||
HAL_StatusTypeDef HAL_QSPI_AutoPolling_IT(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_AutoPollingTypeDef *cfg);
|
||||
|
||||
/* QSPI memory-mapped mode */
|
||||
HAL_StatusTypeDef HAL_QSPI_MemoryMapped(QSPI_HandleTypeDef *hqspi, QSPI_CommandTypeDef *cmd, QSPI_MemoryMappedTypeDef *cfg);
|
||||
|
||||
/* Callback functions in non-blocking modes ***********************************/
|
||||
void HAL_QSPI_ErrorCallback (QSPI_HandleTypeDef *hqspi);
|
||||
void HAL_QSPI_AbortCpltCallback (QSPI_HandleTypeDef *hqspi);
|
||||
void HAL_QSPI_FifoThresholdCallback(QSPI_HandleTypeDef *hqspi);
|
||||
|
||||
/* QSPI indirect mode */
|
||||
void HAL_QSPI_CmdCpltCallback (QSPI_HandleTypeDef *hqspi);
|
||||
void HAL_QSPI_RxCpltCallback (QSPI_HandleTypeDef *hqspi);
|
||||
void HAL_QSPI_TxCpltCallback (QSPI_HandleTypeDef *hqspi);
|
||||
|
||||
/* QSPI status flag polling mode */
|
||||
void HAL_QSPI_StatusMatchCallback (QSPI_HandleTypeDef *hqspi);
|
||||
|
||||
/* QSPI memory-mapped mode */
|
||||
void HAL_QSPI_TimeOutCallback (QSPI_HandleTypeDef *hqspi);
|
||||
|
||||
#if (USE_HAL_QSPI_REGISTER_CALLBACKS == 1)
|
||||
/* QSPI callback registering/unregistering */
|
||||
HAL_StatusTypeDef HAL_QSPI_RegisterCallback (QSPI_HandleTypeDef *hqspi, HAL_QSPI_CallbackIDTypeDef CallbackId, pQSPI_CallbackTypeDef pCallback);
|
||||
HAL_StatusTypeDef HAL_QSPI_UnRegisterCallback (QSPI_HandleTypeDef *hqspi, HAL_QSPI_CallbackIDTypeDef CallbackId);
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup QSPI_Exported_Functions_Group3
|
||||
* @{
|
||||
*/
|
||||
/* Peripheral Control and State functions ************************************/
|
||||
HAL_QSPI_StateTypeDef HAL_QSPI_GetState (const QSPI_HandleTypeDef *hqspi);
|
||||
uint32_t HAL_QSPI_GetError (const QSPI_HandleTypeDef *hqspi);
|
||||
HAL_StatusTypeDef HAL_QSPI_Abort (QSPI_HandleTypeDef *hqspi);
|
||||
HAL_StatusTypeDef HAL_QSPI_Abort_IT (QSPI_HandleTypeDef *hqspi);
|
||||
void HAL_QSPI_SetTimeout (QSPI_HandleTypeDef *hqspi, uint32_t Timeout);
|
||||
HAL_StatusTypeDef HAL_QSPI_SetFifoThreshold(QSPI_HandleTypeDef *hqspi, uint32_t Threshold);
|
||||
uint32_t HAL_QSPI_GetFifoThreshold(const QSPI_HandleTypeDef *hqspi);
|
||||
HAL_StatusTypeDef HAL_QSPI_SetFlashID (QSPI_HandleTypeDef *hqspi, uint32_t FlashID);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* End of exported functions -------------------------------------------------*/
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @defgroup QSPI_Private_Macros QSPI Private Macros
|
||||
* @{
|
||||
*/
|
||||
#define IS_QSPI_CLOCK_PRESCALER(PRESCALER) ((PRESCALER) <= 0xFFU)
|
||||
|
||||
#define IS_QSPI_FIFO_THRESHOLD(THR) (((THR) > 0U) && ((THR) <= 32U))
|
||||
|
||||
#define IS_QSPI_SSHIFT(SSHIFT) (((SSHIFT) == QSPI_SAMPLE_SHIFTING_NONE) || \
|
||||
((SSHIFT) == QSPI_SAMPLE_SHIFTING_HALFCYCLE))
|
||||
|
||||
#define IS_QSPI_FLASH_SIZE(FSIZE) (((FSIZE) <= 31U))
|
||||
|
||||
#define IS_QSPI_CS_HIGH_TIME(CSHTIME) (((CSHTIME) == QSPI_CS_HIGH_TIME_1_CYCLE) || \
|
||||
((CSHTIME) == QSPI_CS_HIGH_TIME_2_CYCLE) || \
|
||||
((CSHTIME) == QSPI_CS_HIGH_TIME_3_CYCLE) || \
|
||||
((CSHTIME) == QSPI_CS_HIGH_TIME_4_CYCLE) || \
|
||||
((CSHTIME) == QSPI_CS_HIGH_TIME_5_CYCLE) || \
|
||||
((CSHTIME) == QSPI_CS_HIGH_TIME_6_CYCLE) || \
|
||||
((CSHTIME) == QSPI_CS_HIGH_TIME_7_CYCLE) || \
|
||||
((CSHTIME) == QSPI_CS_HIGH_TIME_8_CYCLE))
|
||||
|
||||
#define IS_QSPI_CLOCK_MODE(CLKMODE) (((CLKMODE) == QSPI_CLOCK_MODE_0) || \
|
||||
((CLKMODE) == QSPI_CLOCK_MODE_3))
|
||||
|
||||
#define IS_QSPI_FLASH_ID(FLASH_ID) (((FLASH_ID) == QSPI_FLASH_ID_1) || \
|
||||
((FLASH_ID) == QSPI_FLASH_ID_2))
|
||||
|
||||
#define IS_QSPI_DUAL_FLASH_MODE(MODE) (((MODE) == QSPI_DUALFLASH_ENABLE) || \
|
||||
((MODE) == QSPI_DUALFLASH_DISABLE))
|
||||
|
||||
#define IS_QSPI_INSTRUCTION(INSTRUCTION) ((INSTRUCTION) <= 0xFFU)
|
||||
|
||||
#define IS_QSPI_ADDRESS_SIZE(ADDR_SIZE) (((ADDR_SIZE) == QSPI_ADDRESS_8_BITS) || \
|
||||
((ADDR_SIZE) == QSPI_ADDRESS_16_BITS) || \
|
||||
((ADDR_SIZE) == QSPI_ADDRESS_24_BITS) || \
|
||||
((ADDR_SIZE) == QSPI_ADDRESS_32_BITS))
|
||||
|
||||
#define IS_QSPI_ALTERNATE_BYTES_SIZE(SIZE) (((SIZE) == QSPI_ALTERNATE_BYTES_8_BITS) || \
|
||||
((SIZE) == QSPI_ALTERNATE_BYTES_16_BITS) || \
|
||||
((SIZE) == QSPI_ALTERNATE_BYTES_24_BITS) || \
|
||||
((SIZE) == QSPI_ALTERNATE_BYTES_32_BITS))
|
||||
|
||||
#define IS_QSPI_DUMMY_CYCLES(DCY) ((DCY) <= 31U)
|
||||
|
||||
#define IS_QSPI_INSTRUCTION_MODE(MODE) (((MODE) == QSPI_INSTRUCTION_NONE) || \
|
||||
((MODE) == QSPI_INSTRUCTION_1_LINE) || \
|
||||
((MODE) == QSPI_INSTRUCTION_2_LINES) || \
|
||||
((MODE) == QSPI_INSTRUCTION_4_LINES))
|
||||
|
||||
#define IS_QSPI_ADDRESS_MODE(MODE) (((MODE) == QSPI_ADDRESS_NONE) || \
|
||||
((MODE) == QSPI_ADDRESS_1_LINE) || \
|
||||
((MODE) == QSPI_ADDRESS_2_LINES) || \
|
||||
((MODE) == QSPI_ADDRESS_4_LINES))
|
||||
|
||||
#define IS_QSPI_ALTERNATE_BYTES_MODE(MODE) (((MODE) == QSPI_ALTERNATE_BYTES_NONE) || \
|
||||
((MODE) == QSPI_ALTERNATE_BYTES_1_LINE) || \
|
||||
((MODE) == QSPI_ALTERNATE_BYTES_2_LINES) || \
|
||||
((MODE) == QSPI_ALTERNATE_BYTES_4_LINES))
|
||||
|
||||
#define IS_QSPI_DATA_MODE(MODE) (((MODE) == QSPI_DATA_NONE) || \
|
||||
((MODE) == QSPI_DATA_1_LINE) || \
|
||||
((MODE) == QSPI_DATA_2_LINES) || \
|
||||
((MODE) == QSPI_DATA_4_LINES))
|
||||
|
||||
#define IS_QSPI_DDR_MODE(DDR_MODE) (((DDR_MODE) == QSPI_DDR_MODE_DISABLE) || \
|
||||
((DDR_MODE) == QSPI_DDR_MODE_ENABLE))
|
||||
|
||||
#define IS_QSPI_DDR_HHC(DDR_HHC) (((DDR_HHC) == QSPI_DDR_HHC_ANALOG_DELAY) || \
|
||||
((DDR_HHC) == QSPI_DDR_HHC_HALF_CLK_DELAY))
|
||||
|
||||
#define IS_QSPI_SIOO_MODE(SIOO_MODE) (((SIOO_MODE) == QSPI_SIOO_INST_EVERY_CMD) || \
|
||||
((SIOO_MODE) == QSPI_SIOO_INST_ONLY_FIRST_CMD))
|
||||
|
||||
#define IS_QSPI_INTERVAL(INTERVAL) ((INTERVAL) <= QUADSPI_PIR_INTERVAL)
|
||||
|
||||
#define IS_QSPI_STATUS_BYTES_SIZE(SIZE) (((SIZE) >= 1U) && ((SIZE) <= 4U))
|
||||
|
||||
#define IS_QSPI_MATCH_MODE(MODE) (((MODE) == QSPI_MATCH_MODE_AND) || \
|
||||
((MODE) == QSPI_MATCH_MODE_OR))
|
||||
|
||||
#define IS_QSPI_AUTOMATIC_STOP(APMS) (((APMS) == QSPI_AUTOMATIC_STOP_DISABLE) || \
|
||||
((APMS) == QSPI_AUTOMATIC_STOP_ENABLE))
|
||||
|
||||
#define IS_QSPI_TIMEOUT_ACTIVATION(TCEN) (((TCEN) == QSPI_TIMEOUT_COUNTER_DISABLE) || \
|
||||
((TCEN) == QSPI_TIMEOUT_COUNTER_ENABLE))
|
||||
|
||||
#define IS_QSPI_TIMEOUT_PERIOD(PERIOD) ((PERIOD) <= 0xFFFFU)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* End of private macros -----------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* defined(QUADSPI) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* STM32H7xx_HAL_QSPI_H */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1157,11 +1157,14 @@
|
||||
<name>$PROJ_DIR$/../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_exti.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$/../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_sdmmc.c</name>
|
||||
<name>$PROJ_DIR$/../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_qspi.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$/../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_delayblock.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$/../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_sdmmc.c</name>
|
||||
</file>
|
||||
<file>
|
||||
<name>$PROJ_DIR$/../Drivers/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_sd.c</name>
|
||||
</file>
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
/* #define HAL_IWDG_MODULE_ENABLED */
|
||||
/* #define HAL_LPTIM_MODULE_ENABLED */
|
||||
/* #define HAL_LTDC_MODULE_ENABLED */
|
||||
/* #define HAL_QSPI_MODULE_ENABLED */
|
||||
#define HAL_QSPI_MODULE_ENABLED
|
||||
/* #define HAL_RAMECC_MODULE_ENABLED */
|
||||
/* #define HAL_RNG_MODULE_ENABLED */
|
||||
/* #define HAL_RTC_MODULE_ENABLED */
|
||||
|
||||
@@ -59,6 +59,7 @@ void DMA1_Stream0_IRQHandler(void);
|
||||
void USART1_IRQHandler(void);
|
||||
void USART2_IRQHandler(void);
|
||||
void SDMMC1_IRQHandler(void);
|
||||
void QUADSPI_IRQHandler(void);
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
+41
-1
@@ -41,6 +41,8 @@
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
|
||||
QSPI_HandleTypeDef hqspi;
|
||||
|
||||
SD_HandleTypeDef hsd1;
|
||||
|
||||
UART_HandleTypeDef huart1;
|
||||
@@ -62,6 +64,7 @@ static void MX_FMC_Init(void);
|
||||
static void MX_SDMMC1_SD_Init(void);
|
||||
static void MX_USART1_UART_Init(void);
|
||||
static void MX_USART2_UART_Init(void);
|
||||
static void MX_QUADSPI_Init(void);
|
||||
/* USER CODE BEGIN PFP */
|
||||
|
||||
/* USER CODE END PFP */
|
||||
@@ -108,6 +111,7 @@ __WEAK int main(void)
|
||||
MX_SDMMC1_SD_Init();
|
||||
MX_USART1_UART_Init();
|
||||
MX_USART2_UART_Init();
|
||||
MX_QUADSPI_Init();
|
||||
/* USER CODE BEGIN 2 */
|
||||
|
||||
/* USER CODE END 2 */
|
||||
@@ -153,7 +157,7 @@ void SystemClock_Config(void)
|
||||
RCC_OscInitStruct.PLL.PLLM = 4;
|
||||
RCC_OscInitStruct.PLL.PLLN = 60;
|
||||
RCC_OscInitStruct.PLL.PLLP = 2;
|
||||
RCC_OscInitStruct.PLL.PLLQ = 6;
|
||||
RCC_OscInitStruct.PLL.PLLQ = 8;
|
||||
RCC_OscInitStruct.PLL.PLLR = 2;
|
||||
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
|
||||
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
|
||||
@@ -182,6 +186,41 @@ void SystemClock_Config(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QUADSPI Initialization Function
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
static void MX_QUADSPI_Init(void)
|
||||
{
|
||||
|
||||
/* USER CODE BEGIN QUADSPI_Init 0 */
|
||||
|
||||
/* USER CODE END QUADSPI_Init 0 */
|
||||
|
||||
/* USER CODE BEGIN QUADSPI_Init 1 */
|
||||
|
||||
/* USER CODE END QUADSPI_Init 1 */
|
||||
/* QUADSPI parameter configuration*/
|
||||
hqspi.Instance = QUADSPI;
|
||||
hqspi.Init.ClockPrescaler = 255;
|
||||
hqspi.Init.FifoThreshold = 1;
|
||||
hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
|
||||
hqspi.Init.FlashSize = 1;
|
||||
hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE;
|
||||
hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
|
||||
hqspi.Init.FlashID = QSPI_FLASH_ID_1;
|
||||
hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
|
||||
if (HAL_QSPI_Init(&hqspi) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
/* USER CODE BEGIN QUADSPI_Init 2 */
|
||||
|
||||
/* USER CODE END QUADSPI_Init 2 */
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SDMMC1 Initialization Function
|
||||
* @param None
|
||||
@@ -387,6 +426,7 @@ static void MX_GPIO_Init(void)
|
||||
/* GPIO Ports Clock Enable */
|
||||
__HAL_RCC_GPIOF_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOH_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOG_CLK_ENABLE();
|
||||
|
||||
@@ -77,6 +77,120 @@ void HAL_MspInit(void)
|
||||
/* USER CODE END MspInit 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QSPI MSP Initialization
|
||||
* This function configures the hardware resources used in this example
|
||||
* @param hqspi: QSPI handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_QSPI_MspInit(QSPI_HandleTypeDef* hqspi)
|
||||
{
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
|
||||
if(hqspi->Instance==QUADSPI)
|
||||
{
|
||||
/* USER CODE BEGIN QUADSPI_MspInit 0 */
|
||||
|
||||
/* USER CODE END QUADSPI_MspInit 0 */
|
||||
|
||||
/** Initializes the peripherals clock
|
||||
*/
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_QSPI;
|
||||
PeriphClkInitStruct.QspiClockSelection = RCC_QSPICLKSOURCE_PLL;
|
||||
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_QSPI_CLK_ENABLE();
|
||||
|
||||
__HAL_RCC_GPIOF_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
/**QUADSPI GPIO Configuration
|
||||
PF6 ------> QUADSPI_BK1_IO3
|
||||
PF7 ------> QUADSPI_BK1_IO2
|
||||
PF8 ------> QUADSPI_BK1_IO0
|
||||
PF9 ------> QUADSPI_BK1_IO1
|
||||
PB2 ------> QUADSPI_CLK
|
||||
PB6 ------> QUADSPI_BK1_NCS
|
||||
*/
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
|
||||
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
|
||||
HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_2;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_6;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
|
||||
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
|
||||
|
||||
/* QUADSPI interrupt Init */
|
||||
HAL_NVIC_SetPriority(QUADSPI_IRQn, 0, 0);
|
||||
HAL_NVIC_EnableIRQ(QUADSPI_IRQn);
|
||||
/* USER CODE BEGIN QUADSPI_MspInit 1 */
|
||||
|
||||
/* USER CODE END QUADSPI_MspInit 1 */
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief QSPI MSP De-Initialization
|
||||
* This function freeze the hardware resources used in this example
|
||||
* @param hqspi: QSPI handle pointer
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_QSPI_MspDeInit(QSPI_HandleTypeDef* hqspi)
|
||||
{
|
||||
if(hqspi->Instance==QUADSPI)
|
||||
{
|
||||
/* USER CODE BEGIN QUADSPI_MspDeInit 0 */
|
||||
|
||||
/* USER CODE END QUADSPI_MspDeInit 0 */
|
||||
/* Peripheral clock disable */
|
||||
__HAL_RCC_QSPI_CLK_DISABLE();
|
||||
|
||||
/**QUADSPI GPIO Configuration
|
||||
PF6 ------> QUADSPI_BK1_IO3
|
||||
PF7 ------> QUADSPI_BK1_IO2
|
||||
PF8 ------> QUADSPI_BK1_IO0
|
||||
PF9 ------> QUADSPI_BK1_IO1
|
||||
PB2 ------> QUADSPI_CLK
|
||||
PB6 ------> QUADSPI_BK1_NCS
|
||||
*/
|
||||
HAL_GPIO_DeInit(GPIOF, GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9);
|
||||
|
||||
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_2|GPIO_PIN_6);
|
||||
|
||||
/* QUADSPI interrupt DeInit */
|
||||
HAL_NVIC_DisableIRQ(QUADSPI_IRQn);
|
||||
/* USER CODE BEGIN QUADSPI_MspDeInit 1 */
|
||||
|
||||
/* USER CODE END QUADSPI_MspDeInit 1 */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SD MSP Initialization
|
||||
* This function configures the hardware resources used in this example
|
||||
@@ -271,17 +385,17 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart)
|
||||
/* Peripheral clock enable */
|
||||
__HAL_RCC_USART2_CLK_ENABLE();
|
||||
|
||||
__HAL_RCC_GPIOD_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
/**USART2 GPIO Configuration
|
||||
PD5 ------> USART2_TX
|
||||
PD6 ------> USART2_RX
|
||||
PA2 ------> USART2_TX
|
||||
PA3 ------> USART2_RX
|
||||
*/
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
|
||||
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
/* USART2 interrupt Init */
|
||||
HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
|
||||
@@ -333,10 +447,10 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
|
||||
__HAL_RCC_USART2_CLK_DISABLE();
|
||||
|
||||
/**USART2 GPIO Configuration
|
||||
PD5 ------> USART2_TX
|
||||
PD6 ------> USART2_RX
|
||||
PA2 ------> USART2_TX
|
||||
PA3 ------> USART2_RX
|
||||
*/
|
||||
HAL_GPIO_DeInit(GPIOD, GPIO_PIN_5|GPIO_PIN_6);
|
||||
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);
|
||||
|
||||
/* USART2 interrupt DeInit */
|
||||
HAL_NVIC_DisableIRQ(USART2_IRQn);
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
/* USER CODE END 0 */
|
||||
|
||||
/* External variables --------------------------------------------------------*/
|
||||
extern QSPI_HandleTypeDef hqspi;
|
||||
extern SD_HandleTypeDef hsd1;
|
||||
extern DMA_HandleTypeDef hdma_usart1_rx;
|
||||
extern UART_HandleTypeDef huart1;
|
||||
@@ -257,6 +258,20 @@ void SDMMC1_IRQHandler(void)
|
||||
/* USER CODE END SDMMC1_IRQn 1 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles QUADSPI global interrupt.
|
||||
*/
|
||||
void QUADSPI_IRQHandler(void)
|
||||
{
|
||||
/* USER CODE BEGIN QUADSPI_IRQn 0 */
|
||||
|
||||
/* USER CODE END QUADSPI_IRQn 0 */
|
||||
HAL_QSPI_IRQHandler(&hqspi);
|
||||
/* USER CODE BEGIN QUADSPI_IRQn 1 */
|
||||
|
||||
/* USER CODE END QUADSPI_IRQn 1 */
|
||||
}
|
||||
|
||||
/* USER CODE BEGIN 1 */
|
||||
|
||||
/* USER CODE END 1 */
|
||||
+99
-72
@@ -36,71 +36,78 @@ Mcu.CPN=STM32H743IIT6
|
||||
Mcu.Family=STM32H7
|
||||
Mcu.IP0=CORTEX_M7
|
||||
Mcu.IP1=DMA
|
||||
Mcu.IP10=USART2
|
||||
Mcu.IP2=FMC
|
||||
Mcu.IP3=MEMORYMAP
|
||||
Mcu.IP4=NVIC
|
||||
Mcu.IP5=RCC
|
||||
Mcu.IP6=SDMMC1
|
||||
Mcu.IP7=SYS
|
||||
Mcu.IP8=USART1
|
||||
Mcu.IP9=USART2
|
||||
Mcu.IPNb=10
|
||||
Mcu.IP5=QUADSPI
|
||||
Mcu.IP6=RCC
|
||||
Mcu.IP7=SDMMC1
|
||||
Mcu.IP8=SYS
|
||||
Mcu.IP9=USART1
|
||||
Mcu.IPNb=11
|
||||
Mcu.Name=STM32H743IITx
|
||||
Mcu.Package=LQFP176
|
||||
Mcu.Pin0=PF0
|
||||
Mcu.Pin1=PF1
|
||||
Mcu.Pin10=PB1
|
||||
Mcu.Pin11=PF11
|
||||
Mcu.Pin12=PF12
|
||||
Mcu.Pin13=PF13
|
||||
Mcu.Pin14=PF14
|
||||
Mcu.Pin15=PF15
|
||||
Mcu.Pin16=PG0
|
||||
Mcu.Pin17=PG1
|
||||
Mcu.Pin18=PE7
|
||||
Mcu.Pin19=PE8
|
||||
Mcu.Pin10=PC0
|
||||
Mcu.Pin11=PA2
|
||||
Mcu.Pin12=PH2
|
||||
Mcu.Pin13=PH3
|
||||
Mcu.Pin14=PA3
|
||||
Mcu.Pin15=PB0
|
||||
Mcu.Pin16=PB1
|
||||
Mcu.Pin17=PB2
|
||||
Mcu.Pin18=PF11
|
||||
Mcu.Pin19=PF12
|
||||
Mcu.Pin2=PF2
|
||||
Mcu.Pin20=PE9
|
||||
Mcu.Pin21=PE10
|
||||
Mcu.Pin22=PE11
|
||||
Mcu.Pin23=PE12
|
||||
Mcu.Pin24=PE13
|
||||
Mcu.Pin25=PE14
|
||||
Mcu.Pin26=PE15
|
||||
Mcu.Pin27=PB14
|
||||
Mcu.Pin28=PB15
|
||||
Mcu.Pin29=PD8
|
||||
Mcu.Pin20=PF13
|
||||
Mcu.Pin21=PF14
|
||||
Mcu.Pin22=PF15
|
||||
Mcu.Pin23=PG0
|
||||
Mcu.Pin24=PG1
|
||||
Mcu.Pin25=PE7
|
||||
Mcu.Pin26=PE8
|
||||
Mcu.Pin27=PE9
|
||||
Mcu.Pin28=PE10
|
||||
Mcu.Pin29=PE11
|
||||
Mcu.Pin3=PF3
|
||||
Mcu.Pin30=PD9
|
||||
Mcu.Pin31=PD10
|
||||
Mcu.Pin32=PD14
|
||||
Mcu.Pin33=PD15
|
||||
Mcu.Pin34=PG2
|
||||
Mcu.Pin35=PG4
|
||||
Mcu.Pin36=PG5
|
||||
Mcu.Pin37=PG8
|
||||
Mcu.Pin38=PC8
|
||||
Mcu.Pin39=PC9
|
||||
Mcu.Pin30=PE12
|
||||
Mcu.Pin31=PE13
|
||||
Mcu.Pin32=PE14
|
||||
Mcu.Pin33=PE15
|
||||
Mcu.Pin34=PB14
|
||||
Mcu.Pin35=PB15
|
||||
Mcu.Pin36=PD8
|
||||
Mcu.Pin37=PD9
|
||||
Mcu.Pin38=PD10
|
||||
Mcu.Pin39=PD14
|
||||
Mcu.Pin4=PF4
|
||||
Mcu.Pin40=PC10
|
||||
Mcu.Pin41=PC11
|
||||
Mcu.Pin42=PC12
|
||||
Mcu.Pin43=PD0
|
||||
Mcu.Pin44=PD1
|
||||
Mcu.Pin45=PD2
|
||||
Mcu.Pin46=PD5
|
||||
Mcu.Pin47=PD6
|
||||
Mcu.Pin48=PG15
|
||||
Mcu.Pin49=PE0
|
||||
Mcu.Pin40=PD15
|
||||
Mcu.Pin41=PG2
|
||||
Mcu.Pin42=PG4
|
||||
Mcu.Pin43=PG5
|
||||
Mcu.Pin44=PG8
|
||||
Mcu.Pin45=PC8
|
||||
Mcu.Pin46=PC9
|
||||
Mcu.Pin47=PC10
|
||||
Mcu.Pin48=PC11
|
||||
Mcu.Pin49=PC12
|
||||
Mcu.Pin5=PF5
|
||||
Mcu.Pin50=PE1
|
||||
Mcu.Pin51=VP_SYS_VS_Systick
|
||||
Mcu.Pin52=VP_MEMORYMAP_VS_MEMORYMAP
|
||||
Mcu.Pin6=PC0
|
||||
Mcu.Pin7=PH2
|
||||
Mcu.Pin8=PH3
|
||||
Mcu.Pin9=PB0
|
||||
Mcu.PinsNb=53
|
||||
Mcu.Pin50=PD0
|
||||
Mcu.Pin51=PD1
|
||||
Mcu.Pin52=PD2
|
||||
Mcu.Pin53=PG15
|
||||
Mcu.Pin54=PB6
|
||||
Mcu.Pin55=PE0
|
||||
Mcu.Pin56=PE1
|
||||
Mcu.Pin57=VP_SYS_VS_Systick
|
||||
Mcu.Pin58=VP_MEMORYMAP_VS_MEMORYMAP
|
||||
Mcu.Pin6=PF6
|
||||
Mcu.Pin7=PF7
|
||||
Mcu.Pin8=PF8
|
||||
Mcu.Pin9=PF9
|
||||
Mcu.PinsNb=59
|
||||
Mcu.ThirdPartyNb=0
|
||||
Mcu.UserConstants=
|
||||
Mcu.UserName=STM32H743IITx
|
||||
@@ -115,12 +122,17 @@ NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||
NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
||||
NVIC.QUADSPI_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
|
||||
NVIC.SDMMC1_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
|
||||
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:false\:true\:false
|
||||
NVIC.USART1_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
|
||||
NVIC.USART2_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
|
||||
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
|
||||
PA2.Mode=Asynchronous
|
||||
PA2.Signal=USART2_TX
|
||||
PA3.Mode=Asynchronous
|
||||
PA3.Signal=USART2_RX
|
||||
PB0.Locked=true
|
||||
PB0.Signal=GPIO_Output
|
||||
PB1.Locked=true
|
||||
@@ -129,6 +141,12 @@ PB14.Mode=Asynchronous
|
||||
PB14.Signal=USART1_TX
|
||||
PB15.Mode=Asynchronous
|
||||
PB15.Signal=USART1_RX
|
||||
PB2.Locked=true
|
||||
PB2.Mode=Single Bank 1
|
||||
PB2.Signal=QUADSPI_CLK
|
||||
PB6.Locked=true
|
||||
PB6.Mode=Single Bank 1
|
||||
PB6.Signal=QUADSPI_BK1_NCS
|
||||
PC0.Signal=FMC_SDNWE
|
||||
PC10.Mode=SD_4_bits_Wide_bus
|
||||
PC10.Signal=SDMMC1_D2
|
||||
@@ -147,10 +165,6 @@ PD14.Signal=FMC_D0_DA0
|
||||
PD15.Signal=FMC_D1_DA1
|
||||
PD2.Mode=SD_4_bits_Wide_bus
|
||||
PD2.Signal=SDMMC1_CMD
|
||||
PD5.Mode=Asynchronous
|
||||
PD5.Signal=USART2_TX
|
||||
PD6.Mode=Asynchronous
|
||||
PD6.Signal=USART2_RX
|
||||
PD8.Signal=FMC_D13_DA13
|
||||
PD9.Signal=FMC_D14_DA14
|
||||
PE0.Signal=FMC_NBL0
|
||||
@@ -175,6 +189,18 @@ PF2.Signal=FMC_A2
|
||||
PF3.Signal=FMC_A3
|
||||
PF4.Signal=FMC_A4
|
||||
PF5.Signal=FMC_A5
|
||||
PF6.Locked=true
|
||||
PF6.Mode=Single Bank 1
|
||||
PF6.Signal=QUADSPI_BK1_IO3
|
||||
PF7.Locked=true
|
||||
PF7.Mode=Single Bank 1
|
||||
PF7.Signal=QUADSPI_BK1_IO2
|
||||
PF8.Locked=true
|
||||
PF8.Mode=Single Bank 1
|
||||
PF8.Signal=QUADSPI_BK1_IO0
|
||||
PF9.Locked=true
|
||||
PF9.Mode=Single Bank 1
|
||||
PF9.Signal=QUADSPI_BK1_IO1
|
||||
PG0.Signal=FMC_A10
|
||||
PG1.Signal=FMC_A11
|
||||
PG15.Signal=FMC_SDNCAS
|
||||
@@ -220,7 +246,7 @@ ProjectManager.ToolChainLocation=
|
||||
ProjectManager.UAScriptAfterPath=
|
||||
ProjectManager.UAScriptBeforePath=
|
||||
ProjectManager.UnderRoot=false
|
||||
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_FMC_Init-FMC-false-HAL-true,5-MX_SDMMC1_SD_Init-SDMMC1-false-HAL-true,6-MX_USART1_UART_Init-USART1-false-HAL-true,7-MX_USART2_UART_Init-USART2-false-HAL-true,8-MX_LTDC_Init-LTDC-false-HAL-true,0-MX_CORTEX_M7_Init-CORTEX_M7-false-HAL-true
|
||||
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_FMC_Init-FMC-false-HAL-true,5-MX_SDMMC1_SD_Init-SDMMC1-false-HAL-true,6-MX_USART1_UART_Init-USART1-false-HAL-true,7-MX_USART2_UART_Init-USART2-false-HAL-true,0-MX_CORTEX_M7_Init-CORTEX_M7-false-HAL-true
|
||||
RCC.ADCFreq_Value=150000000
|
||||
RCC.AHB12Freq_Value=240000000
|
||||
RCC.AHB4Freq_Value=240000000
|
||||
@@ -238,7 +264,7 @@ RCC.D1PPRE=RCC_APB3_DIV2
|
||||
RCC.D2PPRE1=RCC_APB1_DIV2
|
||||
RCC.D2PPRE2=RCC_APB2_DIV2
|
||||
RCC.D3PPRE=RCC_APB4_DIV2
|
||||
RCC.DFSDMACLkFreq_Value=160000000
|
||||
RCC.DFSDMACLkFreq_Value=120000000
|
||||
RCC.DFSDMFreq_Value=120000000
|
||||
RCC.DIVM1=4
|
||||
RCC.DIVN1=60
|
||||
@@ -246,14 +272,14 @@ RCC.DIVN2=150
|
||||
RCC.DIVP1Freq_Value=480000000
|
||||
RCC.DIVP2Freq_Value=150000000
|
||||
RCC.DIVP3Freq_Value=129000000
|
||||
RCC.DIVQ1=6
|
||||
RCC.DIVQ1Freq_Value=160000000
|
||||
RCC.DIVQ1=8
|
||||
RCC.DIVQ1Freq_Value=120000000
|
||||
RCC.DIVQ2Freq_Value=150000000
|
||||
RCC.DIVQ3Freq_Value=129000000
|
||||
RCC.DIVR1Freq_Value=480000000
|
||||
RCC.DIVR2Freq_Value=150000000
|
||||
RCC.DIVR3Freq_Value=129000000
|
||||
RCC.FDCANFreq_Value=160000000
|
||||
RCC.FDCANFreq_Value=120000000
|
||||
RCC.FMCFreq_Value=240000000
|
||||
RCC.FamilyName=M
|
||||
RCC.HCLK3ClockFreq_Value=240000000
|
||||
@@ -262,7 +288,7 @@ RCC.HPRE=RCC_HCLK_DIV2
|
||||
RCC.HRTIMFreq_Value=240000000
|
||||
RCC.I2C123Freq_Value=120000000
|
||||
RCC.I2C4Freq_Value=120000000
|
||||
RCC.IPParameters=ADCFreq_Value,AHB12Freq_Value,AHB4Freq_Value,APB1Freq_Value,APB2Freq_Value,APB3Freq_Value,APB4Freq_Value,AXIClockFreq_Value,CECFreq_Value,CKPERFreq_Value,CortexFreq_Value,CpuClockFreq_Value,D1CPREFreq_Value,D1PPRE,D2PPRE1,D2PPRE2,D3PPRE,DFSDMACLkFreq_Value,DFSDMFreq_Value,DIVM1,DIVN1,DIVN2,DIVP1Freq_Value,DIVP2Freq_Value,DIVP3Freq_Value,DIVQ1,DIVQ1Freq_Value,DIVQ2Freq_Value,DIVQ3Freq_Value,DIVR1Freq_Value,DIVR2Freq_Value,DIVR3Freq_Value,FDCANFreq_Value,FMCFreq_Value,FamilyName,HCLK3ClockFreq_Value,HCLKFreq_Value,HPRE,HRTIMFreq_Value,I2C123Freq_Value,I2C4Freq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPTIM345Freq_Value,LPUART1Freq_Value,LTDCFreq_Value,MCO1PinFreq_Value,MCO2PinFreq_Value,PLL2FRACN,PLL3FRACN,PLLFRACN,QSPIFreq_Value,RNGFreq_Value,RTCFreq_Value,SAI1Freq_Value,SAI23Freq_Value,SAI4AFreq_Value,SAI4BFreq_Value,SDMMC1CLockSelection,SDMMCFreq_Value,SPDIFRXFreq_Value,SPI123Freq_Value,SPI45Freq_Value,SPI6Freq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,Tim1OutputFreq_Value,Tim2OutputFreq_Value,TraceFreq_Value,USART16Freq_Value,USART234578Freq_Value,USBFreq_Value,VCO1OutputFreq_Value,VCO2OutputFreq_Value,VCO3OutputFreq_Value,VCOInput1Freq_Value,VCOInput2Freq_Value,VCOInput3Freq_Value
|
||||
RCC.IPParameters=ADCFreq_Value,AHB12Freq_Value,AHB4Freq_Value,APB1Freq_Value,APB2Freq_Value,APB3Freq_Value,APB4Freq_Value,AXIClockFreq_Value,CECFreq_Value,CKPERFreq_Value,CortexFreq_Value,CpuClockFreq_Value,D1CPREFreq_Value,D1PPRE,D2PPRE1,D2PPRE2,D3PPRE,DFSDMACLkFreq_Value,DFSDMFreq_Value,DIVM1,DIVN1,DIVN2,DIVP1Freq_Value,DIVP2Freq_Value,DIVP3Freq_Value,DIVQ1,DIVQ1Freq_Value,DIVQ2Freq_Value,DIVQ3Freq_Value,DIVR1Freq_Value,DIVR2Freq_Value,DIVR3Freq_Value,FDCANFreq_Value,FMCFreq_Value,FamilyName,HCLK3ClockFreq_Value,HCLKFreq_Value,HPRE,HRTIMFreq_Value,I2C123Freq_Value,I2C4Freq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPTIM345Freq_Value,LPUART1Freq_Value,LTDCFreq_Value,MCO1PinFreq_Value,MCO2PinFreq_Value,PLL2FRACN,PLL3FRACN,PLLFRACN,QSPICLockSelection,QSPIFreq_Value,RNGFreq_Value,RTCFreq_Value,SAI1Freq_Value,SAI23Freq_Value,SAI4AFreq_Value,SAI4BFreq_Value,SDMMC1CLockSelection,SDMMCFreq_Value,SPDIFRXFreq_Value,SPI123Freq_Value,SPI45Freq_Value,SPI6Freq_Value,SWPMI1Freq_Value,SYSCLKFreq_VALUE,SYSCLKSource,Tim1OutputFreq_Value,Tim2OutputFreq_Value,TraceFreq_Value,USART16Freq_Value,USART234578Freq_Value,USBFreq_Value,VCO1OutputFreq_Value,VCO2OutputFreq_Value,VCO3OutputFreq_Value,VCOInput1Freq_Value,VCOInput2Freq_Value,VCOInput3Freq_Value
|
||||
RCC.LPTIM1Freq_Value=120000000
|
||||
RCC.LPTIM2Freq_Value=120000000
|
||||
RCC.LPTIM345Freq_Value=120000000
|
||||
@@ -273,17 +299,18 @@ RCC.MCO2PinFreq_Value=480000000
|
||||
RCC.PLL2FRACN=0
|
||||
RCC.PLL3FRACN=0
|
||||
RCC.PLLFRACN=0
|
||||
RCC.QSPIFreq_Value=240000000
|
||||
RCC.QSPICLockSelection=RCC_QSPICLKSOURCE_PLL
|
||||
RCC.QSPIFreq_Value=120000000
|
||||
RCC.RNGFreq_Value=48000000
|
||||
RCC.RTCFreq_Value=32000
|
||||
RCC.SAI1Freq_Value=160000000
|
||||
RCC.SAI23Freq_Value=160000000
|
||||
RCC.SAI4AFreq_Value=160000000
|
||||
RCC.SAI4BFreq_Value=160000000
|
||||
RCC.SAI1Freq_Value=120000000
|
||||
RCC.SAI23Freq_Value=120000000
|
||||
RCC.SAI4AFreq_Value=120000000
|
||||
RCC.SAI4BFreq_Value=120000000
|
||||
RCC.SDMMC1CLockSelection=RCC_SDMMCCLKSOURCE_PLL2
|
||||
RCC.SDMMCFreq_Value=150000000
|
||||
RCC.SPDIFRXFreq_Value=160000000
|
||||
RCC.SPI123Freq_Value=160000000
|
||||
RCC.SPDIFRXFreq_Value=120000000
|
||||
RCC.SPI123Freq_Value=120000000
|
||||
RCC.SPI45Freq_Value=120000000
|
||||
RCC.SPI6Freq_Value=120000000
|
||||
RCC.SWPMI1Freq_Value=120000000
|
||||
@@ -294,7 +321,7 @@ RCC.Tim2OutputFreq_Value=240000000
|
||||
RCC.TraceFreq_Value=64000000
|
||||
RCC.USART16Freq_Value=120000000
|
||||
RCC.USART234578Freq_Value=120000000
|
||||
RCC.USBFreq_Value=160000000
|
||||
RCC.USBFreq_Value=120000000
|
||||
RCC.VCO1OutputFreq_Value=960000000
|
||||
RCC.VCO2OutputFreq_Value=300000000
|
||||
RCC.VCO3OutputFreq_Value=258000000
|
||||
|
||||
+1
-1
@@ -174,7 +174,7 @@ extern "C"
|
||||
*/
|
||||
|
||||
/*#define BSP_USING_QSPI*/
|
||||
|
||||
#define BSP_USING_QSPI
|
||||
/*-------------------------- QSPI CONFIG END --------------------------*/
|
||||
|
||||
/*-------------------------- PWM CONFIG BEGIN --------------------------*/
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
# GitHub really wants to mark littlefs as a python project, telling it to
|
||||
# reclassify our test .toml files as C code (which they are 95% of anyways)
|
||||
# remedies this
|
||||
*.toml linguist-language=c
|
||||
@@ -0,0 +1,34 @@
|
||||
# Compilation output
|
||||
*.o
|
||||
*.d
|
||||
*.a
|
||||
*.ci
|
||||
*.csv
|
||||
*.t.*
|
||||
*.b.*
|
||||
*.gcno
|
||||
*.gcda
|
||||
*.perf
|
||||
lfs
|
||||
liblfs.a
|
||||
|
||||
# Testing things
|
||||
runners/test_runner
|
||||
runners/bench_runner
|
||||
lfs.code.csv
|
||||
lfs.data.csv
|
||||
lfs.stack.csv
|
||||
lfs.structs.csv
|
||||
lfs.cov.csv
|
||||
lfs.perf.csv
|
||||
lfs.perfbd.csv
|
||||
lfs.test.csv
|
||||
lfs.bench.csv
|
||||
|
||||
# Misc
|
||||
tags
|
||||
.gdb_history
|
||||
scripts/__pycache__
|
||||
|
||||
# Historical, probably should remove at some point
|
||||
tests/*.toml.*
|
||||
Vendored
+2173
File diff suppressed because it is too large.
Load diff
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
Copyright (c) 2022, The littlefs authors.
|
||||
Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
- Neither the name of ARM nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
Vendored
+342
@@ -0,0 +1,342 @@
|
||||
## littlefs for RT-Thread
|
||||
|
||||
A little fail-safe filesystem designed for microcontrollers.
|
||||
|
||||
```
|
||||
| | | .---._____
|
||||
.-----. | |
|
||||
--|o |---| littlefs |
|
||||
--| |---| |
|
||||
'-----' '----------'
|
||||
| | |
|
||||
```
|
||||
|
||||
**Power-loss resilience** - littlefs is designed to handle random power
|
||||
failures. All file operations have strong copy-on-write guarantees and if
|
||||
power is lost the filesystem will fall back to the last known good state.
|
||||
|
||||
**Dynamic wear leveling** - littlefs is designed with flash in mind, and
|
||||
provides wear leveling over dynamic blocks. Additionally, littlefs can
|
||||
detect bad blocks and work around them.
|
||||
|
||||
**Bounded RAM/ROM** - littlefs is designed to work with a small amount of
|
||||
memory. RAM usage is strictly bounded, which means RAM consumption does not
|
||||
change as the filesystem grows. The filesystem contains no unbounded
|
||||
recursion and dynamic memory is limited to configurable buffers that can be
|
||||
provided statically.
|
||||
|
||||
## Example
|
||||
|
||||
Here's a simple example that updates a file named `boot_count` every time
|
||||
main runs. The program can be interrupted at any time without losing track
|
||||
of how many times it has been booted and without corrupting the filesystem:
|
||||
|
||||
``` c
|
||||
#include "lfs.h"
|
||||
|
||||
// variables used by the filesystem
|
||||
lfs_t lfs;
|
||||
lfs_file_t file;
|
||||
|
||||
// configuration of the filesystem is provided by this struct
|
||||
const struct lfs_config cfg = {
|
||||
// block device operations
|
||||
.read = user_provided_block_device_read,
|
||||
.prog = user_provided_block_device_prog,
|
||||
.erase = user_provided_block_device_erase,
|
||||
.sync = user_provided_block_device_sync,
|
||||
|
||||
// block device configuration
|
||||
.read_size = 16,
|
||||
.prog_size = 16,
|
||||
.block_size = 4096,
|
||||
.block_count = 128,
|
||||
.cache_size = 16,
|
||||
.lookahead_size = 16,
|
||||
.block_cycles = 500,
|
||||
};
|
||||
|
||||
// entry point
|
||||
int main(void) {
|
||||
// mount the filesystem
|
||||
int err = lfs_mount(&lfs, &cfg);
|
||||
|
||||
// reformat if we can't mount the filesystem
|
||||
// this should only happen on the first boot
|
||||
if (err) {
|
||||
lfs_format(&lfs, &cfg);
|
||||
lfs_mount(&lfs, &cfg);
|
||||
}
|
||||
|
||||
// read current count
|
||||
uint32_t boot_count = 0;
|
||||
lfs_file_open(&lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT);
|
||||
lfs_file_read(&lfs, &file, &boot_count, sizeof(boot_count));
|
||||
|
||||
// update boot count
|
||||
boot_count += 1;
|
||||
lfs_file_rewind(&lfs, &file);
|
||||
lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count));
|
||||
|
||||
// remember the storage is not updated until the file is closed successfully
|
||||
lfs_file_close(&lfs, &file);
|
||||
|
||||
// release any resources we were using
|
||||
lfs_unmount(&lfs);
|
||||
|
||||
// print the boot count
|
||||
printf("boot_count: %d\n", boot_count);
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
Detailed documentation (or at least as much detail as is currently available)
|
||||
can be found in the comments in [lfs.h](lfs.h).
|
||||
|
||||
littlefs takes in a configuration structure that defines how the filesystem
|
||||
operates. The configuration struct provides the filesystem with the block
|
||||
device operations and dimensions, tweakable parameters that tradeoff memory
|
||||
usage for performance, and optional static buffers if the user wants to avoid
|
||||
dynamic memory.
|
||||
|
||||
The state of the littlefs is stored in the `lfs_t` type which is left up
|
||||
to the user to allocate, allowing multiple filesystems to be in use
|
||||
simultaneously. With the `lfs_t` and configuration struct, a user can
|
||||
format a block device or mount the filesystem.
|
||||
|
||||
Once mounted, the littlefs provides a full set of POSIX-like file and
|
||||
directory functions, with the deviation that the allocation of filesystem
|
||||
structures must be provided by the user.
|
||||
|
||||
All POSIX operations, such as remove and rename, are atomic, even in event
|
||||
of power-loss. Additionally, file updates are not actually committed to
|
||||
the filesystem until sync or close is called on the file.
|
||||
|
||||
## Other notes
|
||||
|
||||
Littlefs is written in C, and specifically should compile with any compiler
|
||||
that conforms to the `C99` standard.
|
||||
|
||||
All littlefs calls have the potential to return a negative error code. The
|
||||
errors can be either one of those found in the `enum lfs_error` in
|
||||
[lfs.h](lfs.h), or an error returned by the user's block device operations.
|
||||
|
||||
In the configuration struct, the `prog` and `erase` function provided by the
|
||||
user may return a `LFS_ERR_CORRUPT` error if the implementation already can
|
||||
detect corrupt blocks. However, the wear leveling does not depend on the return
|
||||
code of these functions, instead all data is read back and checked for
|
||||
integrity.
|
||||
|
||||
If your storage caches writes, make sure that the provided `sync` function
|
||||
flushes all the data to memory and ensures that the next read fetches the data
|
||||
from memory, otherwise data integrity can not be guaranteed. If the `write`
|
||||
function does not perform caching, and therefore each `read` or `write` call
|
||||
hits the memory, the `sync` function can simply return 0.
|
||||
|
||||
## Design
|
||||
|
||||
At a high level, littlefs is a block based filesystem that uses small logs to
|
||||
store metadata and larger copy-on-write (COW) structures to store file data.
|
||||
|
||||
In littlefs, these ingredients form a sort of two-layered cake, with the small
|
||||
logs (called metadata pairs) providing fast updates to metadata anywhere on
|
||||
storage, while the COW structures store file data compactly and without any
|
||||
wear amplification cost.
|
||||
|
||||
Both of these data structures are built out of blocks, which are fed by a
|
||||
common block allocator. By limiting the number of erases allowed on a block
|
||||
per allocation, the allocator provides dynamic wear leveling over the entire
|
||||
filesystem.
|
||||
|
||||
```
|
||||
root
|
||||
.--------.--------.
|
||||
| A'| B'| |
|
||||
| | |-> |
|
||||
| | | |
|
||||
'--------'--------'
|
||||
.----' '--------------.
|
||||
A v B v
|
||||
.--------.--------. .--------.--------.
|
||||
| C'| D'| | | E'|new| |
|
||||
| | |-> | | | E'|-> |
|
||||
| | | | | | | |
|
||||
'--------'--------' '--------'--------'
|
||||
.-' '--. | '------------------.
|
||||
v v .-' v
|
||||
.--------. .--------. v .--------.
|
||||
| C | | D | .--------. write | new E |
|
||||
| | | | | E | ==> | |
|
||||
| | | | | | | |
|
||||
'--------' '--------' | | '--------'
|
||||
'--------' .-' |
|
||||
.-' '-. .-------------|------'
|
||||
v v v v
|
||||
.--------. .--------. .--------.
|
||||
| F | | G | | new F |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
'--------' '--------' '--------'
|
||||
```
|
||||
|
||||
More details on how littlefs works can be found in [DESIGN.md](DESIGN.md) and
|
||||
[SPEC.md](SPEC.md).
|
||||
|
||||
- [DESIGN.md](DESIGN.md) - A fully detailed dive into how littlefs works.
|
||||
I would suggest reading it as the tradeoffs at work are quite interesting.
|
||||
|
||||
- [SPEC.md](SPEC.md) - The on-disk specification of littlefs with all the
|
||||
nitty-gritty details. May be useful for tooling development.
|
||||
|
||||
## Testing
|
||||
|
||||
The littlefs comes with a test suite designed to run on a PC using the
|
||||
[emulated block device](bd/lfs_testbd.h) found in the `bd` directory.
|
||||
The tests assume a Linux environment and can be started with make:
|
||||
|
||||
``` bash
|
||||
make test
|
||||
```
|
||||
|
||||
Tests are implemented in C in the .toml files found in the `tests` directory.
|
||||
When developing a feature or fixing a bug, it is frequently useful to run a
|
||||
single test case or suite of tests:
|
||||
|
||||
``` bash
|
||||
./scripts/test.py -l runners/test_runner # list available test suites
|
||||
./scripts/test.py -L runners/test_runner test_dirs # list available test cases
|
||||
./scripts/test.py runners/test_runner test_dirs # run a specific test suite
|
||||
```
|
||||
|
||||
If an assert fails in a test, test.py will try to print information about the
|
||||
failure:
|
||||
|
||||
``` bash
|
||||
tests/test_dirs.toml:1:failure: test_dirs_root:1g12gg2 (PROG_SIZE=16, ERASE_SIZE=512) failed
|
||||
tests/test_dirs.toml:5:assert: assert failed with 0, expected eq 42
|
||||
lfs_mount(&lfs, cfg) => 42;
|
||||
```
|
||||
|
||||
This includes the test id, which can be passed to test.py to run only that
|
||||
specific test permutation:
|
||||
|
||||
``` bash
|
||||
./scripts/test.py runners/test_runner test_dirs_root:1g12gg2 # run a specific test permutation
|
||||
./scripts/test.py runners/test_runner test_dirs_root:1g12gg2 --gdb # drop into gdb on failure
|
||||
```
|
||||
|
||||
Some other flags that may be useful:
|
||||
|
||||
```bash
|
||||
./scripts/test.py runners/test_runner -b -j # run tests in parallel
|
||||
./scripts/test.py runners/test_runner -v -O- # redirect stdout to stdout
|
||||
./scripts/test.py runners/test_runner -ddisk # capture resulting disk image
|
||||
```
|
||||
|
||||
See `-h/--help` for a full list of available flags:
|
||||
|
||||
``` bash
|
||||
./scripts/test.py --help
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
The littlefs is provided under the [BSD-3-Clause] license. See
|
||||
[LICENSE.md](LICENSE.md) for more information. Contributions to this project
|
||||
are accepted under the same license.
|
||||
|
||||
Individual files contain the following tag instead of the full license text.
|
||||
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
This enables machine processing of license information based on the SPDX
|
||||
License Identifiers that are here available: http://spdx.org/licenses/
|
||||
|
||||
## Related projects
|
||||
|
||||
- [littlefs-fuse] - A [FUSE] wrapper for littlefs. The project allows you to
|
||||
mount littlefs directly on a Linux machine. Can be useful for debugging
|
||||
littlefs if you have an SD card handy.
|
||||
|
||||
- [littlefs-js] - A javascript wrapper for littlefs. I'm not sure why you would
|
||||
want this, but it is handy for demos. You can see it in action
|
||||
[here][littlefs-js-demo].
|
||||
|
||||
- [littlefs-python] - A Python wrapper for littlefs. The project allows you
|
||||
to create images of the filesystem on your PC. Check if littlefs will fit
|
||||
your needs, create images for a later download to the target memory or
|
||||
inspect the content of a binary image of the target memory.
|
||||
|
||||
- [littlefs-toy] - A command-line tool for creating and working with littlefs
|
||||
images. Uses syntax similar to tar command for ease of use. Supports working
|
||||
on littlefs images embedded inside another file (firmware image, etc).
|
||||
|
||||
- [littlefs2-rust] - A Rust wrapper for littlefs. This project allows you
|
||||
to use littlefs in a Rust-friendly API, reaping the benefits of Rust's memory
|
||||
safety and other guarantees.
|
||||
|
||||
- [nim-littlefs] - A Nim wrapper and API for littlefs. Includes a fuse
|
||||
implementation based on [littlefs-fuse]
|
||||
|
||||
- [chamelon] - A pure-OCaml implementation of (most of) littlefs, designed for
|
||||
use with the MirageOS library operating system project. It is interoperable
|
||||
with the reference implementation, with some caveats.
|
||||
|
||||
- [littlefs-disk-img-viewer] - A memory-efficient web application for viewing
|
||||
littlefs disk images in your web browser.
|
||||
|
||||
- [mklfs] - A command line tool for creating littlefs images. Used in the Lua
|
||||
RTOS ecosystem.
|
||||
|
||||
- [mklittlefs] - A command line tool for creating littlefs images. Used in the
|
||||
ESP8266 and RP2040 ecosystem.
|
||||
|
||||
- [pico-littlefs-usb] - An interface for littlefs that emulates a FAT12
|
||||
filesystem over USB. Allows mounting littlefs on a host PC without additional
|
||||
drivers.
|
||||
|
||||
- [ramcrc32bd] - An example block device using littlefs's 32-bit CRC for
|
||||
error-correction.
|
||||
|
||||
- [ramrsbd] - An example block device using Reed-Solomon codes for
|
||||
error-correction.
|
||||
|
||||
- [Mbed OS] - The easiest way to get started with littlefs is to jump into Mbed
|
||||
which already has block device drivers for most forms of embedded storage.
|
||||
littlefs is available in Mbed OS as the [LittleFileSystem] class.
|
||||
|
||||
- [SPIFFS] - Another excellent embedded filesystem for NOR flash. As a more
|
||||
traditional logging filesystem with full static wear-leveling, SPIFFS will
|
||||
likely outperform littlefs on small memories such as the internal flash on
|
||||
microcontrollers.
|
||||
|
||||
- [Dhara] - An interesting NAND flash translation layer designed for small
|
||||
MCUs. It offers static wear-leveling and power-resilience with only a fixed
|
||||
_O(|address|)_ pointer structure stored on each block and in RAM.
|
||||
|
||||
- [ChaN's FatFs] - A lightweight reimplementation of the infamous FAT filesystem
|
||||
for microcontroller-scale devices. Due to limitations of FAT it can't provide
|
||||
power-loss resilience, but it does allow easy interop with PCs.
|
||||
|
||||
[BSD-3-Clause]: https://spdx.org/licenses/BSD-3-Clause.html
|
||||
[littlefs-fuse]: https://github.com/geky/littlefs-fuse
|
||||
[FUSE]: https://github.com/libfuse/libfuse
|
||||
[littlefs-js]: https://github.com/geky/littlefs-js
|
||||
[littlefs-js-demo]:http://littlefs.geky.net/demo.html
|
||||
[littlefs-python]: https://pypi.org/project/littlefs-python/
|
||||
[littlefs-toy]: https://github.com/tjko/littlefs-toy
|
||||
[littlefs2-rust]: https://crates.io/crates/littlefs2
|
||||
[nim-littlefs]: https://github.com/Graveflo/nim-littlefs
|
||||
[chamelon]: https://github.com/yomimono/chamelon
|
||||
[littlefs-disk-img-viewer]: https://github.com/tniessen/littlefs-disk-img-viewer
|
||||
[mklfs]: https://github.com/whitecatboard/Lua-RTOS-ESP32/tree/master/components/mklfs/src
|
||||
[mklittlefs]: https://github.com/earlephilhower/mklittlefs
|
||||
[pico-littlefs-usb]: https://github.com/oyama/pico-littlefs-usb
|
||||
[ramcrc32bd]: https://github.com/geky/ramcrc32bd
|
||||
[ramrsbd]: https://github.com/geky/ramrsbd
|
||||
[Mbed OS]: https://github.com/armmbed/mbed-os
|
||||
[LittleFileSystem]: https://os.mbed.com/docs/mbed-os/latest/apis/littlefilesystem.html
|
||||
[SPIFFS]: https://github.com/pellepl/spiffs
|
||||
[Dhara]: https://github.com/dlbeer/dhara
|
||||
[ChaN's FatFs]: http://elm-chan.org/fsw/ff/00index_e.html
|
||||
Vendored
+25
@@ -0,0 +1,25 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.cpp')
|
||||
CPPPATH = [cwd]
|
||||
CPPDEFINES = ['LFS_CONFIG=lfs_config.h']
|
||||
|
||||
#delate non-used files
|
||||
try:
|
||||
shutil.rmtree(os.path.join(cwd,'.github'))
|
||||
shutil.rmtree(os.path.join(cwd,'bd'))
|
||||
shutil.rmtree(os.path.join(cwd,'scripts'))
|
||||
shutil.rmtree(os.path.join(cwd,'tests'))
|
||||
os.remove(os.path.join(cwd,'Makefile'))
|
||||
except:
|
||||
pass
|
||||
|
||||
group = DefineGroup('littlefs', src, depend = ['PKG_USING_LITTLEFS', 'RT_USING_DFS'], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
|
||||
|
||||
Return('group')
|
||||
Vendored
+867
@@ -0,0 +1,867 @@
|
||||
## littlefs technical specification
|
||||
|
||||
This is the technical specification of the little filesystem with on-disk
|
||||
version lfs2.1. This document covers the technical details of how the littlefs
|
||||
is stored on disk for introspection and tooling. This document assumes you are
|
||||
familiar with the design of the littlefs, for more info on how littlefs works
|
||||
check out [DESIGN.md](DESIGN.md).
|
||||
|
||||
```
|
||||
| | | .---._____
|
||||
.-----. | |
|
||||
--|o |---| littlefs |
|
||||
--| |---| |
|
||||
'-----' '----------'
|
||||
| | |
|
||||
```
|
||||
|
||||
## Some quick notes
|
||||
|
||||
- littlefs is a block-based filesystem. The disk is divided into an array of
|
||||
evenly sized blocks that are used as the logical unit of storage.
|
||||
|
||||
- Block pointers are stored in 32 bits, with the special value `0xffffffff`
|
||||
representing a null block address.
|
||||
|
||||
- In addition to the logical block size (which usually matches the erase
|
||||
block size), littlefs also uses a program block size and read block size.
|
||||
These determine the alignment of block device operations, but don't need
|
||||
to be consistent for portability.
|
||||
|
||||
- By default, all values in littlefs are stored in little-endian byte order.
|
||||
|
||||
## Directories / Metadata pairs
|
||||
|
||||
Metadata pairs form the backbone of littlefs and provide a system for
|
||||
distributed atomic updates. Even the superblock is stored in a metadata pair.
|
||||
|
||||
As their name suggests, a metadata pair is stored in two blocks, with one block
|
||||
providing a backup during erase cycles in case power is lost. These two blocks
|
||||
are not necessarily sequential and may be anywhere on disk, so a "pointer" to a
|
||||
metadata pair is stored as two block pointers.
|
||||
|
||||
On top of this, each metadata block behaves as an appendable log, containing a
|
||||
variable number of commits. Commits can be appended to the metadata log in
|
||||
order to update the metadata without requiring an erase cycles. Note that
|
||||
successive commits may supersede the metadata in previous commits. Only the
|
||||
most recent metadata should be considered valid.
|
||||
|
||||
The high-level layout of a metadata block is fairly simple:
|
||||
|
||||
```
|
||||
.---------------------------------------.
|
||||
.-| revision count | entries | \
|
||||
| |-------------------+ | |
|
||||
| | | |
|
||||
| | | +-- 1st commit
|
||||
| | | |
|
||||
| | +-------------------| |
|
||||
| | | CRC | /
|
||||
| |-------------------+-------------------|
|
||||
| | entries | \
|
||||
| | | |
|
||||
| | | +-- 2nd commit
|
||||
| | +-------------------+--------------| |
|
||||
| | | CRC | padding | /
|
||||
| |----+-------------------+--------------|
|
||||
| | entries | \
|
||||
| | | |
|
||||
| | | +-- 3rd commit
|
||||
| | +-------------------+---------| |
|
||||
| | | CRC | | /
|
||||
| |---------+-------------------+ |
|
||||
| | unwritten storage | more commits
|
||||
| | | |
|
||||
| | | v
|
||||
| | |
|
||||
| | |
|
||||
| '---------------------------------------'
|
||||
'---------------------------------------'
|
||||
```
|
||||
|
||||
Each metadata block contains a 32-bit revision count followed by a number of
|
||||
commits. Each commit contains a variable number of metadata entries followed
|
||||
by a 32-bit CRC.
|
||||
|
||||
Note also that entries aren't necessarily word-aligned. This allows us to
|
||||
store metadata more compactly, however we can only write to addresses that are
|
||||
aligned to our program block size. This means each commit may have padding for
|
||||
alignment.
|
||||
|
||||
Metadata block fields:
|
||||
|
||||
1. **Revision count (32-bits)** - Incremented every erase cycle. If both blocks
|
||||
contain valid commits, only the block with the most recent revision count
|
||||
should be used. Sequence comparison must be used to avoid issues with
|
||||
integer overflow.
|
||||
|
||||
2. **CRC (32-bits)** - Detects corruption from power-loss or other write
|
||||
issues. Uses a CRC-32 with a polynomial of `0x04c11db7` initialized
|
||||
with `0xffffffff`.
|
||||
|
||||
Entries themselves are stored as a 32-bit tag followed by a variable length
|
||||
blob of data. But exactly how these tags are stored is a little bit tricky.
|
||||
|
||||
Metadata blocks support both forward and backward iteration. In order to do
|
||||
this without duplicating the space for each tag, neighboring entries have their
|
||||
tags XORed together, starting with `0xffffffff`.
|
||||
|
||||
```
|
||||
Forward iteration Backward iteration
|
||||
|
||||
.-------------------. 0xffffffff .-------------------.
|
||||
| revision count | | | revision count |
|
||||
|-------------------| v |-------------------|
|
||||
| tag ~A |---> xor -> tag A | tag ~A |---> xor -> 0xffffffff
|
||||
|-------------------| | |-------------------| ^
|
||||
| data A | | | data A | |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
|-------------------| v |-------------------| |
|
||||
| tag AxB |---> xor -> tag B | tag AxB |---> xor -> tag A
|
||||
|-------------------| | |-------------------| ^
|
||||
| data B | | | data B | |
|
||||
| | | | | |
|
||||
| | | | | |
|
||||
|-------------------| v |-------------------| |
|
||||
| tag BxC |---> xor -> tag C | tag BxC |---> xor -> tag B
|
||||
|-------------------| |-------------------| ^
|
||||
| data C | | data C | |
|
||||
| | | | tag C
|
||||
| | | |
|
||||
| | | |
|
||||
'-------------------' '-------------------'
|
||||
```
|
||||
|
||||
Here's a more complete example of metadata block containing 4 entries:
|
||||
|
||||
```
|
||||
.---------------------------------------.
|
||||
.-| revision count | tag ~A | \
|
||||
| |-------------------+-------------------| |
|
||||
| | data A | |
|
||||
| | | |
|
||||
| |-------------------+-------------------| |
|
||||
| | tag AxB | data B | <--. |
|
||||
| |-------------------+ | | |
|
||||
| | | | +-- 1st commit
|
||||
| | +-------------------+---------| | |
|
||||
| | | tag BxC | | <-.| |
|
||||
| |---------+-------------------+ | || |
|
||||
| | data C | || |
|
||||
| | | || |
|
||||
| |-------------------+-------------------| || |
|
||||
| | tag CxCRC | CRC | || /
|
||||
| |-------------------+-------------------| ||
|
||||
| | tag CRCxA' | data A' | || \
|
||||
| |-------------------+ | || |
|
||||
| | | || |
|
||||
| | +-------------------+----| || +-- 2nd commit
|
||||
| | | tag CRCxA' | | || |
|
||||
| |--------------+-------------------+----| || |
|
||||
| | CRC | padding | || /
|
||||
| |--------------+----+-------------------| ||
|
||||
| | tag CRCxA'' | data A'' | <---. \
|
||||
| |-------------------+ | ||| |
|
||||
| | | ||| |
|
||||
| | +-------------------+---------| ||| |
|
||||
| | | tag A''xD | | < ||| |
|
||||
| |---------+-------------------+ | |||| +-- 3rd commit
|
||||
| | data D | |||| |
|
||||
| | +---------| |||| |
|
||||
| | | tag Dx| |||| |
|
||||
| |---------+-------------------+---------| |||| |
|
||||
| |CRC | CRC | | |||| /
|
||||
| |---------+-------------------+ | ||||
|
||||
| | unwritten storage | |||| more commits
|
||||
| | | |||| |
|
||||
| | | |||| v
|
||||
| | | ||||
|
||||
| | | ||||
|
||||
| '---------------------------------------' ||||
|
||||
'---------------------------------------' |||'- most recent A
|
||||
||'-- most recent B
|
||||
|'--- most recent C
|
||||
'---- most recent D
|
||||
```
|
||||
|
||||
Two things to note before we get into the details around tag encoding:
|
||||
|
||||
1. Each tag contains a valid bit used to indicate if the tag and containing
|
||||
commit is valid. After XORing, this bit should always be zero.
|
||||
|
||||
At the end of each commit, the valid bit of the previous tag is XORed
|
||||
with the lowest bit in the type field of the CRC tag. This allows
|
||||
the CRC tag to force the next commit to fail the valid bit test if it
|
||||
has not yet been written to.
|
||||
|
||||
2. The valid bit alone is not enough info to know if the next commit has been
|
||||
erased. We don't know the order bits will be programmed in a program block,
|
||||
so it's possible that the next commit had an attempted program that left the
|
||||
valid bit unchanged.
|
||||
|
||||
To ensure we only ever program erased bytes, each commit can contain an
|
||||
optional forward-CRC (FCRC). An FCRC contains a checksum of some amount of
|
||||
bytes in the next commit at the time it was erased.
|
||||
|
||||
```
|
||||
.-------------------. \ \
|
||||
| revision count | | |
|
||||
|-------------------| | |
|
||||
| metadata | | |
|
||||
| | +---. +-- current commit
|
||||
| | | | |
|
||||
|-------------------| | | |
|
||||
| FCRC ---|-. | |
|
||||
|-------------------| / | | |
|
||||
| CRC -----|-' /
|
||||
|-------------------| |
|
||||
| padding | | padding (does't need CRC)
|
||||
| | |
|
||||
|-------------------| \ | \
|
||||
| erased? | +-' |
|
||||
| | | | +-- next commit
|
||||
| v | / |
|
||||
| | /
|
||||
| |
|
||||
'-------------------'
|
||||
```
|
||||
|
||||
If the FCRC is missing or the checksum does not match, we must assume a
|
||||
commit was attempted but failed due to power-loss.
|
||||
|
||||
Note that end-of-block commits do not need an FCRC.
|
||||
|
||||
## Metadata tags
|
||||
|
||||
So in littlefs, 32-bit tags describe every type of metadata. And this means
|
||||
_every_ type of metadata, including file entries, directory fields, and
|
||||
global state. Even the CRCs used to mark the end of commits get their own tag.
|
||||
|
||||
Because of this, the tag format contains some densely packed information. Note
|
||||
that there are multiple levels of types which break down into more info:
|
||||
|
||||
```
|
||||
[---- 32 ----]
|
||||
[1|-- 11 --|-- 10 --|-- 10 --]
|
||||
^. ^ . ^ ^- length
|
||||
|. | . '------------ id
|
||||
|. '-----.------------------ type (type3)
|
||||
'.-----------.------------------ valid bit
|
||||
[-3-|-- 8 --]
|
||||
^ ^- chunk
|
||||
'------- type (type1)
|
||||
```
|
||||
|
||||
|
||||
Before we go further, there's one important thing to note. These tags are
|
||||
**not** stored in little-endian. Tags stored in commits are actually stored
|
||||
in big-endian (and is the only thing in littlefs stored in big-endian). This
|
||||
little bit of craziness comes from the fact that the valid bit must be the
|
||||
first bit in a commit, and when converted to little-endian, the valid bit finds
|
||||
itself in byte 4. We could restructure the tag to store the valid bit lower,
|
||||
but, because none of the fields are byte-aligned, this would be more
|
||||
complicated than just storing the tag in big-endian.
|
||||
|
||||
Another thing to note is that both the tags `0x00000000` and `0xffffffff` are
|
||||
invalid and can be used for null values.
|
||||
|
||||
Metadata tag fields:
|
||||
|
||||
1. **Valid bit (1-bit)** - Indicates if the tag is valid.
|
||||
|
||||
2. **Type3 (11-bits)** - Type of the tag. This field is broken down further
|
||||
into a 3-bit abstract type and an 8-bit chunk field. Note that the value
|
||||
`0x000` is invalid and not assigned a type.
|
||||
|
||||
1. **Type1 (3-bits)** - Abstract type of the tag. Groups the tags into
|
||||
8 categories that facilitate bitmasked lookups.
|
||||
|
||||
2. **Chunk (8-bits)** - Chunk field used for various purposes by the different
|
||||
abstract types. type1+chunk+id form a unique identifier for each tag in the
|
||||
metadata block.
|
||||
|
||||
3. **Id (10-bits)** - File id associated with the tag. Each file in a metadata
|
||||
block gets a unique id which is used to associate tags with that file. The
|
||||
special value `0x3ff` is used for any tags that are not associated with a
|
||||
file, such as directory and global metadata.
|
||||
|
||||
4. **Length (10-bits)** - Length of the data in bytes. The special value
|
||||
`0x3ff` indicates that this tag has been deleted.
|
||||
|
||||
## Metadata types
|
||||
|
||||
What follows is an exhaustive list of metadata in littlefs.
|
||||
|
||||
---
|
||||
#### `0x401` LFS_TYPE_CREATE
|
||||
|
||||
Creates a new file with this id. Note that files in a metadata block
|
||||
don't necessarily need a create tag. All a create does is move over any
|
||||
files using this id. In this sense a create is similar to insertion into
|
||||
an imaginary array of files.
|
||||
|
||||
The create and delete tags allow littlefs to keep files in a directory
|
||||
ordered alphabetically by filename.
|
||||
|
||||
---
|
||||
#### `0x4ff` LFS_TYPE_DELETE
|
||||
|
||||
Deletes the file with this id. An inverse to create, this tag moves over
|
||||
any files neighboring this id similar to a deletion from an imaginary
|
||||
array of files.
|
||||
|
||||
---
|
||||
#### `0x0xx` LFS_TYPE_NAME
|
||||
|
||||
Associates the id with a file name and file type.
|
||||
|
||||
The data contains the file name stored as an ASCII string (may be expanded to
|
||||
UTF8 in the future).
|
||||
|
||||
The chunk field in this tag indicates an 8-bit file type which can be one of
|
||||
the following.
|
||||
|
||||
Currently, the name tag must precede any other tags associated with the id and
|
||||
can not be reassigned without deleting the file.
|
||||
|
||||
Layout of the name tag:
|
||||
|
||||
```
|
||||
tag data
|
||||
[-- 32 --][--- variable length ---]
|
||||
[1| 3| 8 | 10 | 10 ][--- (size * 8) ---]
|
||||
^ ^ ^ ^ ^- size ^- file name
|
||||
| | | '------ id
|
||||
| | '----------- file type
|
||||
| '-------------- type1 (0x0)
|
||||
'----------------- valid bit
|
||||
```
|
||||
|
||||
Name fields:
|
||||
|
||||
1. **file type (8-bits)** - Type of the file.
|
||||
|
||||
2. **file name** - File name stored as an ASCII string.
|
||||
|
||||
---
|
||||
#### `0x001` LFS_TYPE_REG
|
||||
|
||||
Initializes the id + name as a regular file.
|
||||
|
||||
How each file is stored depends on its struct tag, which is described below.
|
||||
|
||||
---
|
||||
#### `0x002` LFS_TYPE_DIR
|
||||
|
||||
Initializes the id + name as a directory.
|
||||
|
||||
Directories in littlefs are stored on disk as a linked-list of metadata pairs,
|
||||
each pair containing any number of files in alphabetical order. A pointer to
|
||||
the directory is stored in the struct tag, which is described below.
|
||||
|
||||
---
|
||||
#### `0x0ff` LFS_TYPE_SUPERBLOCK
|
||||
|
||||
Initializes the id as a superblock entry.
|
||||
|
||||
The superblock entry is a special entry used to store format-time configuration
|
||||
and identify the filesystem.
|
||||
|
||||
The name is a bit of a misnomer. While the superblock entry serves the same
|
||||
purpose as a superblock found in other filesystems, in littlefs the superblock
|
||||
does not get a dedicated block. Instead, the superblock entry is duplicated
|
||||
across a linked-list of metadata pairs rooted on the blocks 0 and 1. The last
|
||||
metadata pair doubles as the root directory of the filesystem.
|
||||
|
||||
```
|
||||
.--------. .--------. .--------. .--------. .--------.
|
||||
.| super |->| super |->| super |->| super |->| file B |
|
||||
|| block | || block | || block | || block | || file C |
|
||||
|| | || | || | || file A | || file D |
|
||||
|'--------' |'--------' |'--------' |'--------' |'--------'
|
||||
'--------' '--------' '--------' '--------' '--------'
|
||||
|
||||
\----------------+----------------/ \----------+----------/
|
||||
superblock pairs root directory
|
||||
```
|
||||
|
||||
The filesystem starts with only the root directory. The superblock metadata
|
||||
pairs grow every time the root pair is compacted in order to prolong the
|
||||
life of the device exponentially.
|
||||
|
||||
The contents of the superblock entry are stored in a name tag with the
|
||||
superblock type and an inline-struct tag. The name tag contains the magic
|
||||
string "littlefs", while the inline-struct tag contains version and
|
||||
configuration information.
|
||||
|
||||
Layout of the superblock name tag and inline-struct tag:
|
||||
|
||||
```
|
||||
tag data
|
||||
[-- 32 --][-- 32 --|-- 32 --]
|
||||
[1|- 11 -| 10 | 10 ][--- 64 ---]
|
||||
^ ^ ^ ^- size (8) ^- magic string ("littlefs")
|
||||
| | '------ id (0)
|
||||
| '------------ type (0x0ff)
|
||||
'----------------- valid bit
|
||||
|
||||
tag data
|
||||
[-- 32 --][-- 32 --|-- 32 --|-- 32 --]
|
||||
[1|- 11 -| 10 | 10 ][-- 32 --|-- 32 --|-- 32 --]
|
||||
^ ^ ^ ^ ^- version ^- block size ^- block count
|
||||
| | | | [-- 32 --|-- 32 --|-- 32 --]
|
||||
| | | | [-- 32 --|-- 32 --|-- 32 --]
|
||||
| | | | ^- name max ^- file max ^- attr max
|
||||
| | | '- size (24)
|
||||
| | '------ id (0)
|
||||
| '------------ type (0x201)
|
||||
'----------------- valid bit
|
||||
```
|
||||
|
||||
Superblock fields:
|
||||
|
||||
1. **Magic string (8-bytes)** - Magic string indicating the presence of
|
||||
littlefs on the device. Must be the string "littlefs".
|
||||
|
||||
2. **Version (32-bits)** - The version of littlefs at format time. The version
|
||||
is encoded in a 32-bit value with the upper 16-bits containing the major
|
||||
version, and the lower 16-bits containing the minor version.
|
||||
|
||||
This specification describes version 2.0 (`0x00020000`).
|
||||
|
||||
3. **Block size (32-bits)** - Size of the logical block size used by the
|
||||
filesystem in bytes.
|
||||
|
||||
4. **Block count (32-bits)** - Number of blocks in the filesystem.
|
||||
|
||||
5. **Name max (32-bits)** - Maximum size of file names in bytes.
|
||||
|
||||
6. **File max (32-bits)** - Maximum size of files in bytes.
|
||||
|
||||
7. **Attr max (32-bits)** - Maximum size of file attributes in bytes.
|
||||
|
||||
The superblock must always be the first entry (id 0) in the metadata pair, and
|
||||
the name tag must always be the first tag in the metadata pair. This makes it
|
||||
so that the magic string "littlefs" will always reside at offset=8 in a valid
|
||||
littlefs superblock.
|
||||
|
||||
---
|
||||
#### `0x2xx` LFS_TYPE_STRUCT
|
||||
|
||||
Associates the id with an on-disk data structure.
|
||||
|
||||
The exact layout of the data depends on the data structure type stored in the
|
||||
chunk field and can be one of the following.
|
||||
|
||||
Any type of struct supersedes all other structs associated with the id. For
|
||||
example, appending a ctz-struct replaces an inline-struct on the same file.
|
||||
|
||||
---
|
||||
#### `0x200` LFS_TYPE_DIRSTRUCT
|
||||
|
||||
Gives the id a directory data structure.
|
||||
|
||||
Directories in littlefs are stored on disk as a linked-list of metadata pairs,
|
||||
each pair containing any number of files in alphabetical order.
|
||||
|
||||
```
|
||||
|
|
||||
v
|
||||
.--------. .--------. .--------. .--------. .--------. .--------.
|
||||
.| file A |->| file D |->| file G |->| file I |->| file J |->| file M |
|
||||
|| file B | || file E | || file H | || | || file K | || file N |
|
||||
|| file C | || file F | || | || | || file L | || |
|
||||
|'--------' |'--------' |'--------' |'--------' |'--------' |'--------'
|
||||
'--------' '--------' '--------' '--------' '--------' '--------'
|
||||
```
|
||||
|
||||
The dir-struct tag contains only the pointer to the first metadata-pair in the
|
||||
directory. The directory size is not known without traversing the directory.
|
||||
|
||||
The pointer to the next metadata-pair in the directory is stored in a tail tag,
|
||||
which is described below.
|
||||
|
||||
Layout of the dir-struct tag:
|
||||
|
||||
```
|
||||
tag data
|
||||
[-- 32 --][-- 32 --|-- 32 --]
|
||||
[1|- 11 -| 10 | 10 ][--- 64 ---]
|
||||
^ ^ ^ ^- size (8) ^- metadata pair
|
||||
| | '------ id
|
||||
| '------------ type (0x200)
|
||||
'----------------- valid bit
|
||||
```
|
||||
|
||||
Dir-struct fields:
|
||||
|
||||
1. **Metadata pair (8-bytes)** - Pointer to the first metadata-pair
|
||||
in the directory.
|
||||
|
||||
---
|
||||
#### `0x201` LFS_TYPE_INLINESTRUCT
|
||||
|
||||
Gives the id an inline data structure.
|
||||
|
||||
Inline structs store small files that can fit in the metadata pair. In this
|
||||
case, the file data is stored directly in the tag's data area.
|
||||
|
||||
Layout of the inline-struct tag:
|
||||
|
||||
```
|
||||
tag data
|
||||
[-- 32 --][--- variable length ---]
|
||||
[1|- 11 -| 10 | 10 ][--- (size * 8) ---]
|
||||
^ ^ ^ ^- size ^- inline data
|
||||
| | '------ id
|
||||
| '------------ type (0x201)
|
||||
'----------------- valid bit
|
||||
```
|
||||
|
||||
Inline-struct fields:
|
||||
|
||||
1. **Inline data** - File data stored directly in the metadata-pair.
|
||||
|
||||
---
|
||||
#### `0x202` LFS_TYPE_CTZSTRUCT
|
||||
|
||||
Gives the id a CTZ skip-list data structure.
|
||||
|
||||
CTZ skip-lists store files that can not fit in the metadata pair. These files
|
||||
are stored in a skip-list in reverse, with a pointer to the head of the
|
||||
skip-list. Note that the head of the skip-list and the file size is enough
|
||||
information to read the file.
|
||||
|
||||
How exactly CTZ skip-lists work is a bit complicated. A full explanation can be
|
||||
found in the [DESIGN.md](DESIGN.md#ctz-skip-lists).
|
||||
|
||||
A quick summary: For every _n_‍th block where _n_ is divisible by
|
||||
2‍_ˣ_, that block contains a pointer to block _n_-2‍_ˣ_.
|
||||
These pointers are stored in increasing order of _x_ in each block of the file
|
||||
before the actual data.
|
||||
|
||||
```
|
||||
|
|
||||
v
|
||||
.--------. .--------. .--------. .--------. .--------. .--------.
|
||||
| A |<-| D |<-| G |<-| J |<-| M |<-| P |
|
||||
| B |<-| E |--| H |<-| K |--| N | | Q |
|
||||
| C |<-| F |--| I |--| L |--| O | | |
|
||||
'--------' '--------' '--------' '--------' '--------' '--------'
|
||||
block 0 block 1 block 2 block 3 block 4 block 5
|
||||
1 skip 2 skips 1 skip 3 skips 1 skip
|
||||
```
|
||||
|
||||
Note that the maximum number of pointers in a block is bounded by the maximum
|
||||
file size divided by the block size. With 32 bits for file size, this results
|
||||
in a minimum block size of 104 bytes.
|
||||
|
||||
Layout of the CTZ-struct tag:
|
||||
|
||||
```
|
||||
tag data
|
||||
[-- 32 --][-- 32 --|-- 32 --]
|
||||
[1|- 11 -| 10 | 10 ][-- 32 --|-- 32 --]
|
||||
^ ^ ^ ^ ^ ^- file size
|
||||
| | | | '-------------------- file head
|
||||
| | | '- size (8)
|
||||
| | '------ id
|
||||
| '------------ type (0x202)
|
||||
'----------------- valid bit
|
||||
```
|
||||
|
||||
CTZ-struct fields:
|
||||
|
||||
1. **File head (32-bits)** - Pointer to the block that is the head of the
|
||||
file's CTZ skip-list.
|
||||
|
||||
2. **File size (32-bits)** - Size of the file in bytes.
|
||||
|
||||
---
|
||||
#### `0x3xx` LFS_TYPE_USERATTR
|
||||
|
||||
Attaches a user attribute to an id.
|
||||
|
||||
littlefs has a concept of "user attributes". These are small user-provided
|
||||
attributes that can be used to store things like timestamps, hashes,
|
||||
permissions, etc.
|
||||
|
||||
Each user attribute is uniquely identified by an 8-bit type which is stored in
|
||||
the chunk field, and the user attribute itself can be found in the tag's data.
|
||||
|
||||
There are currently no standard user attributes and a portable littlefs
|
||||
implementation should work with any user attributes missing.
|
||||
|
||||
Layout of the user-attr tag:
|
||||
|
||||
```
|
||||
tag data
|
||||
[-- 32 --][--- variable length ---]
|
||||
[1| 3| 8 | 10 | 10 ][--- (size * 8) ---]
|
||||
^ ^ ^ ^ ^- size ^- attr data
|
||||
| | | '------ id
|
||||
| | '----------- attr type
|
||||
| '-------------- type1 (0x3)
|
||||
'----------------- valid bit
|
||||
```
|
||||
|
||||
User-attr fields:
|
||||
|
||||
1. **Attr type (8-bits)** - Type of the user attributes.
|
||||
|
||||
2. **Attr data** - The data associated with the user attribute.
|
||||
|
||||
---
|
||||
#### `0x6xx` LFS_TYPE_TAIL
|
||||
|
||||
Provides the tail pointer for the metadata pair itself.
|
||||
|
||||
The metadata pair's tail pointer is used in littlefs for a linked-list
|
||||
containing all metadata pairs. The chunk field contains the type of the tail,
|
||||
which indicates if the following metadata pair is a part of the directory
|
||||
(hard-tail) or only used to traverse the filesystem (soft-tail).
|
||||
|
||||
```
|
||||
.--------.
|
||||
.| dir A |-.
|
||||
||softtail| |
|
||||
.--------| |-'
|
||||
| |'--------'
|
||||
| '---|--|-'
|
||||
| .-' '-------------.
|
||||
| v v
|
||||
| .--------. .--------. .--------.
|
||||
'->| dir B |->| dir B |->| dir C |
|
||||
||hardtail| ||softtail| || |
|
||||
|| | || | || |
|
||||
|'--------' |'--------' |'--------'
|
||||
'--------' '--------' '--------'
|
||||
```
|
||||
|
||||
Currently any type supersedes any other preceding tails in the metadata pair,
|
||||
but this may change if additional metadata pair state is added.
|
||||
|
||||
A note about the metadata pair linked-list: Normally, this linked-list contains
|
||||
every metadata pair in the filesystem. However, there are some operations that
|
||||
can cause this linked-list to become out of sync if a power-loss were to occur.
|
||||
When this happens, littlefs sets the "sync" flag in the global state. How
|
||||
exactly this flag is stored is described below.
|
||||
|
||||
When the sync flag is set:
|
||||
|
||||
1. The linked-list may contain an orphaned directory that has been removed in
|
||||
the filesystem.
|
||||
2. The linked-list may contain a metadata pair with a bad block that has been
|
||||
replaced in the filesystem.
|
||||
|
||||
If the sync flag is set, the threaded linked-list must be checked for these
|
||||
errors before it can be used reliably. Note that the threaded linked-list can
|
||||
be ignored if littlefs is mounted read-only.
|
||||
|
||||
Layout of the tail tag:
|
||||
|
||||
```
|
||||
tag data
|
||||
[-- 32 --][-- 32 --|-- 32 --]
|
||||
[1| 3| 8 | 10 | 10 ][--- 64 ---]
|
||||
^ ^ ^ ^ ^- size (8) ^- metadata pair
|
||||
| | | '------ id
|
||||
| | '---------- tail type
|
||||
| '------------- type1 (0x6)
|
||||
'---------------- valid bit
|
||||
```
|
||||
|
||||
Tail fields:
|
||||
|
||||
1. **Tail type (8-bits)** - Type of the tail pointer.
|
||||
|
||||
2. **Metadata pair (8-bytes)** - Pointer to the next metadata-pair.
|
||||
|
||||
---
|
||||
#### `0x600` LFS_TYPE_SOFTTAIL
|
||||
|
||||
Provides a tail pointer that points to the next metadata pair in the
|
||||
filesystem.
|
||||
|
||||
In this case, the next metadata pair is not a part of our current directory
|
||||
and should only be followed when traversing the entire filesystem.
|
||||
|
||||
---
|
||||
#### `0x601` LFS_TYPE_HARDTAIL
|
||||
|
||||
Provides a tail pointer that points to the next metadata pair in the
|
||||
directory.
|
||||
|
||||
In this case, the next metadata pair belongs to the current directory. Note
|
||||
that because directories in littlefs are sorted alphabetically, the next
|
||||
metadata pair should only contain filenames greater than any filename in the
|
||||
current pair.
|
||||
|
||||
---
|
||||
#### `0x7xx` LFS_TYPE_GSTATE
|
||||
|
||||
Provides delta bits for global state entries.
|
||||
|
||||
littlefs has a concept of "global state". This is a small set of state that
|
||||
can be updated by a commit to _any_ metadata pair in the filesystem.
|
||||
|
||||
The way this works is that the global state is stored as a set of deltas
|
||||
distributed across the filesystem such that the global state can be found by
|
||||
the xor-sum of these deltas.
|
||||
|
||||
```
|
||||
.--------. .--------. .--------. .--------. .--------.
|
||||
.| |->| gdelta |->| |->| gdelta |->| gdelta |
|
||||
|| | || 0x23 | || | || 0xff | || 0xce |
|
||||
|| | || | || | || | || |
|
||||
|'--------' |'--------' |'--------' |'--------' |'--------'
|
||||
'--------' '----|---' '--------' '----|---' '----|---'
|
||||
v v v
|
||||
0x00 --> xor ------------------> xor ------> xor --> gstate = 0x12
|
||||
```
|
||||
|
||||
Note that storing globals this way is very expensive in terms of storage usage,
|
||||
so any global state should be kept very small.
|
||||
|
||||
The size and format of each piece of global state depends on the type, which
|
||||
is stored in the chunk field. Currently, the only global state is move state,
|
||||
which is outlined below.
|
||||
|
||||
---
|
||||
#### `0x7ff` LFS_TYPE_MOVESTATE
|
||||
|
||||
Provides delta bits for the global move state.
|
||||
|
||||
The move state in littlefs is used to store info about operations that could
|
||||
cause to filesystem to go out of sync if the power is lost. The operations
|
||||
where this could occur is moves of files between metadata pairs and any
|
||||
operation that changes metadata pairs on the threaded linked-list.
|
||||
|
||||
In the case of moves, the move state contains a tag + metadata pair describing
|
||||
the source of the ongoing move. If this tag is non-zero, that means that power
|
||||
was lost during a move, and the file exists in two different locations. If this
|
||||
happens, the source of the move should be considered deleted, and the move
|
||||
should be completed (the source should be deleted) before any other write
|
||||
operations to the filesystem.
|
||||
|
||||
In the case of operations to the threaded linked-list, a single "sync" bit is
|
||||
used to indicate that a modification is ongoing. If this sync flag is set, the
|
||||
threaded linked-list will need to be checked for errors before it can be used
|
||||
reliably. The exact cases to check for are described above in the tail tag.
|
||||
|
||||
Layout of the move state:
|
||||
|
||||
```
|
||||
tag data
|
||||
[-- 32 --][-- 32 --|-- 32 --|-- 32 --]
|
||||
[1|- 11 -| 10 | 10 ][1|- 11 -| 10 | 10 |--- 64 ---]
|
||||
^ ^ ^ ^ ^ ^ ^ ^- padding (0) ^- metadata pair
|
||||
| | | | | | '------ move id
|
||||
| | | | | '------------ move type
|
||||
| | | | '----------------- sync bit
|
||||
| | | |
|
||||
| | | '- size (12)
|
||||
| | '------ id (0x3ff)
|
||||
| '------------ type (0x7ff)
|
||||
'----------------- valid bit
|
||||
```
|
||||
|
||||
Move state fields:
|
||||
|
||||
1. **Sync bit (1-bit)** - Indicates if the metadata pair threaded linked-list
|
||||
is in-sync. If set, the threaded linked-list should be checked for errors.
|
||||
|
||||
2. **Move type (11-bits)** - Type of move being performed. Must be either
|
||||
`0x000`, indicating no move, or `0x4ff` indicating the source file should
|
||||
be deleted.
|
||||
|
||||
3. **Move id (10-bits)** - The file id being moved.
|
||||
|
||||
4. **Metadata pair (8-bytes)** - Pointer to the metadata-pair containing
|
||||
the move.
|
||||
|
||||
---
|
||||
#### `0x5xx` LFS_TYPE_CRC
|
||||
|
||||
Last but not least, the CRC tag marks the end of a commit and provides a
|
||||
checksum for any commits to the metadata block.
|
||||
|
||||
The first 32-bits of the data contain a CRC-32 with a polynomial of
|
||||
`0x04c11db7` initialized with `0xffffffff`. This CRC provides a checksum for
|
||||
all metadata since the previous CRC tag, including the CRC tag itself. For
|
||||
the first commit, this includes the revision count for the metadata block.
|
||||
|
||||
However, the size of the data is not limited to 32-bits. The data field may
|
||||
larger to pad the commit to the next program-aligned boundary.
|
||||
|
||||
In addition, the CRC tag's chunk field contains a set of flags which can
|
||||
change the behaviour of commits. Currently the only flag in use is the lowest
|
||||
bit, which determines the expected state of the valid bit for any following
|
||||
tags. This is used to guarantee that unwritten storage in a metadata block
|
||||
will be detected as invalid.
|
||||
|
||||
Layout of the CRC tag:
|
||||
|
||||
```
|
||||
tag data
|
||||
[-- 32 --][-- 32 --|--- variable length ---]
|
||||
[1| 3| 8 | 10 | 10 ][-- 32 --|--- (size * 8 - 32) ---]
|
||||
^ ^ ^ ^ ^ ^- crc ^- padding
|
||||
| | | | '- size
|
||||
| | | '------ id (0x3ff)
|
||||
| | '----------- valid state
|
||||
| '-------------- type1 (0x5)
|
||||
'----------------- valid bit
|
||||
```
|
||||
|
||||
CRC fields:
|
||||
|
||||
1. **Valid state (1-bit)** - Indicates the expected value of the valid bit for
|
||||
any tags in the next commit.
|
||||
|
||||
2. **CRC (32-bits)** - CRC-32 with a polynomial of `0x04c11db7` initialized
|
||||
with `0xffffffff`.
|
||||
|
||||
3. **Padding** - Padding to the next program-aligned boundary. No guarantees
|
||||
are made about the contents.
|
||||
|
||||
---
|
||||
#### `0x5ff` LFS_TYPE_FCRC
|
||||
|
||||
Added in lfs2.1, the optional FCRC tag contains a checksum of some amount of
|
||||
bytes in the next commit at the time it was erased. This allows us to ensure
|
||||
that we only ever program erased bytes, even if a previous commit failed due
|
||||
to power-loss.
|
||||
|
||||
When programming a commit, the FCRC size must be at least as large as the
|
||||
program block size. However, the program block is not saved on disk, and can
|
||||
change between mounts, so the FCRC size on disk may be different than the
|
||||
current program block size.
|
||||
|
||||
If the FCRC is missing or the checksum does not match, we must assume a
|
||||
commit was attempted but failed due to power-loss.
|
||||
|
||||
Layout of the FCRC tag:
|
||||
|
||||
```
|
||||
tag data
|
||||
[-- 32 --][-- 32 --|-- 32 --]
|
||||
[1|- 11 -| 10 | 10 ][-- 32 --|-- 32 --]
|
||||
^ ^ ^ ^ ^- fcrc size ^- fcrc
|
||||
| | | '- size (8)
|
||||
| | '------ id (0x3ff)
|
||||
| '------------ type (0x5ff)
|
||||
'----------------- valid bit
|
||||
```
|
||||
|
||||
FCRC fields:
|
||||
|
||||
1. **FCRC size (32-bits)** - Number of bytes after this commit's CRC tag's
|
||||
padding to include in the FCRC.
|
||||
|
||||
2. **FCRC (32-bits)** - CRC of the bytes after this commit's CRC tag's padding
|
||||
when erased. Like the CRC tag, this uses a CRC-32 with a polynomial of
|
||||
`0x04c11db7` initialized with `0xffffffff`.
|
||||
|
||||
---
|
||||
+270
@@ -0,0 +1,270 @@
|
||||
[cases.bench_dir_open]
|
||||
# 0 = in-order
|
||||
# 1 = reversed-order
|
||||
# 2 = random-order
|
||||
defines.ORDER = [0, 1, 2]
|
||||
defines.N = 1024
|
||||
defines.FILE_SIZE = 8
|
||||
defines.CHUNK_SIZE = 8
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
|
||||
// first create the files
|
||||
char name[256];
|
||||
uint8_t buffer[CHUNK_SIZE];
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
sprintf(name, "file%08x", i);
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, name,
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||
|
||||
uint32_t file_prng = i;
|
||||
for (lfs_size_t j = 0; j < FILE_SIZE; j += CHUNK_SIZE) {
|
||||
for (lfs_size_t k = 0; k < CHUNK_SIZE; k++) {
|
||||
buffer[k] = BENCH_PRNG(&file_prng);
|
||||
}
|
||||
lfs_file_write(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
}
|
||||
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
}
|
||||
|
||||
// then read the files
|
||||
BENCH_START();
|
||||
uint32_t prng = 42;
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
lfs_off_t i_
|
||||
= (ORDER == 0) ? i
|
||||
: (ORDER == 1) ? (N-1-i)
|
||||
: BENCH_PRNG(&prng) % N;
|
||||
sprintf(name, "file%08x", i_);
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, name, LFS_O_RDONLY) => 0;
|
||||
|
||||
uint32_t file_prng = i_;
|
||||
for (lfs_size_t j = 0; j < FILE_SIZE; j += CHUNK_SIZE) {
|
||||
lfs_file_read(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
for (lfs_size_t k = 0; k < CHUNK_SIZE; k++) {
|
||||
assert(buffer[k] == BENCH_PRNG(&file_prng));
|
||||
}
|
||||
}
|
||||
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
}
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
[cases.bench_dir_creat]
|
||||
# 0 = in-order
|
||||
# 1 = reversed-order
|
||||
# 2 = random-order
|
||||
defines.ORDER = [0, 1, 2]
|
||||
defines.N = 1024
|
||||
defines.FILE_SIZE = 8
|
||||
defines.CHUNK_SIZE = 8
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
|
||||
BENCH_START();
|
||||
uint32_t prng = 42;
|
||||
char name[256];
|
||||
uint8_t buffer[CHUNK_SIZE];
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
lfs_off_t i_
|
||||
= (ORDER == 0) ? i
|
||||
: (ORDER == 1) ? (N-1-i)
|
||||
: BENCH_PRNG(&prng) % N;
|
||||
sprintf(name, "file%08x", i_);
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, name,
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC) => 0;
|
||||
|
||||
uint32_t file_prng = i_;
|
||||
for (lfs_size_t j = 0; j < FILE_SIZE; j += CHUNK_SIZE) {
|
||||
for (lfs_size_t k = 0; k < CHUNK_SIZE; k++) {
|
||||
buffer[k] = BENCH_PRNG(&file_prng);
|
||||
}
|
||||
lfs_file_write(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
}
|
||||
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
}
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
[cases.bench_dir_remove]
|
||||
# 0 = in-order
|
||||
# 1 = reversed-order
|
||||
# 2 = random-order
|
||||
defines.ORDER = [0, 1, 2]
|
||||
defines.N = 1024
|
||||
defines.FILE_SIZE = 8
|
||||
defines.CHUNK_SIZE = 8
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
|
||||
// first create the files
|
||||
char name[256];
|
||||
uint8_t buffer[CHUNK_SIZE];
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
sprintf(name, "file%08x", i);
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, name,
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||
|
||||
uint32_t file_prng = i;
|
||||
for (lfs_size_t j = 0; j < FILE_SIZE; j += CHUNK_SIZE) {
|
||||
for (lfs_size_t k = 0; k < CHUNK_SIZE; k++) {
|
||||
buffer[k] = BENCH_PRNG(&file_prng);
|
||||
}
|
||||
lfs_file_write(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
}
|
||||
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
}
|
||||
|
||||
// then remove the files
|
||||
BENCH_START();
|
||||
uint32_t prng = 42;
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
lfs_off_t i_
|
||||
= (ORDER == 0) ? i
|
||||
: (ORDER == 1) ? (N-1-i)
|
||||
: BENCH_PRNG(&prng) % N;
|
||||
sprintf(name, "file%08x", i_);
|
||||
int err = lfs_remove(&lfs, name);
|
||||
assert(!err || err == LFS_ERR_NOENT);
|
||||
}
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
[cases.bench_dir_read]
|
||||
defines.N = 1024
|
||||
defines.FILE_SIZE = 8
|
||||
defines.CHUNK_SIZE = 8
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
|
||||
// first create the files
|
||||
char name[256];
|
||||
uint8_t buffer[CHUNK_SIZE];
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
sprintf(name, "file%08x", i);
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, name,
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||
|
||||
uint32_t file_prng = i;
|
||||
for (lfs_size_t j = 0; j < FILE_SIZE; j += CHUNK_SIZE) {
|
||||
for (lfs_size_t k = 0; k < CHUNK_SIZE; k++) {
|
||||
buffer[k] = BENCH_PRNG(&file_prng);
|
||||
}
|
||||
lfs_file_write(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
}
|
||||
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
}
|
||||
|
||||
// then read the directory
|
||||
BENCH_START();
|
||||
lfs_dir_t dir;
|
||||
lfs_dir_open(&lfs, &dir, "/") => 0;
|
||||
struct lfs_info info;
|
||||
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||
assert(info.type == LFS_TYPE_DIR);
|
||||
assert(strcmp(info.name, ".") == 0);
|
||||
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||
assert(info.type == LFS_TYPE_DIR);
|
||||
assert(strcmp(info.name, "..") == 0);
|
||||
for (int i = 0; i < N; i++) {
|
||||
sprintf(name, "file%08x", i);
|
||||
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||
assert(info.type == LFS_TYPE_REG);
|
||||
assert(strcmp(info.name, name) == 0);
|
||||
}
|
||||
lfs_dir_read(&lfs, &dir, &info) => 0;
|
||||
lfs_dir_close(&lfs, &dir) => 0;
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
[cases.bench_dir_mkdir]
|
||||
# 0 = in-order
|
||||
# 1 = reversed-order
|
||||
# 2 = random-order
|
||||
defines.ORDER = [0, 1, 2]
|
||||
defines.N = 8
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
|
||||
BENCH_START();
|
||||
uint32_t prng = 42;
|
||||
char name[256];
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
lfs_off_t i_
|
||||
= (ORDER == 0) ? i
|
||||
: (ORDER == 1) ? (N-1-i)
|
||||
: BENCH_PRNG(&prng) % N;
|
||||
printf("hm %d\n", i);
|
||||
sprintf(name, "dir%08x", i_);
|
||||
int err = lfs_mkdir(&lfs, name);
|
||||
assert(!err || err == LFS_ERR_EXIST);
|
||||
}
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
[cases.bench_dir_rmdir]
|
||||
# 0 = in-order
|
||||
# 1 = reversed-order
|
||||
# 2 = random-order
|
||||
defines.ORDER = [0, 1, 2]
|
||||
defines.N = 8
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
|
||||
// first create the dirs
|
||||
char name[256];
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
sprintf(name, "dir%08x", i);
|
||||
lfs_mkdir(&lfs, name) => 0;
|
||||
}
|
||||
|
||||
// then remove the dirs
|
||||
BENCH_START();
|
||||
uint32_t prng = 42;
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
lfs_off_t i_
|
||||
= (ORDER == 0) ? i
|
||||
: (ORDER == 1) ? (N-1-i)
|
||||
: BENCH_PRNG(&prng) % N;
|
||||
sprintf(name, "dir%08x", i_);
|
||||
int err = lfs_remove(&lfs, name);
|
||||
assert(!err || err == LFS_ERR_NOENT);
|
||||
}
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
[cases.bench_file_read]
|
||||
# 0 = in-order
|
||||
# 1 = reversed-order
|
||||
# 2 = random-order
|
||||
defines.ORDER = [0, 1, 2]
|
||||
defines.SIZE = '128*1024'
|
||||
defines.CHUNK_SIZE = 64
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_size_t chunks = (SIZE+CHUNK_SIZE-1)/CHUNK_SIZE;
|
||||
|
||||
// first write the file
|
||||
lfs_file_t file;
|
||||
uint8_t buffer[CHUNK_SIZE];
|
||||
lfs_file_open(&lfs, &file, "file",
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||
for (lfs_size_t i = 0; i < chunks; i++) {
|
||||
uint32_t chunk_prng = i;
|
||||
for (lfs_size_t j = 0; j < CHUNK_SIZE; j++) {
|
||||
buffer[j] = BENCH_PRNG(&chunk_prng);
|
||||
}
|
||||
|
||||
lfs_file_write(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
}
|
||||
lfs_file_write(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
|
||||
// then read the file
|
||||
BENCH_START();
|
||||
lfs_file_open(&lfs, &file, "file", LFS_O_RDONLY) => 0;
|
||||
|
||||
uint32_t prng = 42;
|
||||
for (lfs_size_t i = 0; i < chunks; i++) {
|
||||
lfs_off_t i_
|
||||
= (ORDER == 0) ? i
|
||||
: (ORDER == 1) ? (chunks-1-i)
|
||||
: BENCH_PRNG(&prng) % chunks;
|
||||
lfs_file_seek(&lfs, &file, i_*CHUNK_SIZE, LFS_SEEK_SET)
|
||||
=> i_*CHUNK_SIZE;
|
||||
lfs_file_read(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
|
||||
uint32_t chunk_prng = i_;
|
||||
for (lfs_size_t j = 0; j < CHUNK_SIZE; j++) {
|
||||
assert(buffer[j] == BENCH_PRNG(&chunk_prng));
|
||||
}
|
||||
}
|
||||
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
[cases.bench_file_write]
|
||||
# 0 = in-order
|
||||
# 1 = reversed-order
|
||||
# 2 = random-order
|
||||
defines.ORDER = [0, 1, 2]
|
||||
defines.SIZE = '128*1024'
|
||||
defines.CHUNK_SIZE = 64
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_size_t chunks = (SIZE+CHUNK_SIZE-1)/CHUNK_SIZE;
|
||||
|
||||
BENCH_START();
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, "file",
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||
|
||||
uint8_t buffer[CHUNK_SIZE];
|
||||
uint32_t prng = 42;
|
||||
for (lfs_size_t i = 0; i < chunks; i++) {
|
||||
lfs_off_t i_
|
||||
= (ORDER == 0) ? i
|
||||
: (ORDER == 1) ? (chunks-1-i)
|
||||
: BENCH_PRNG(&prng) % chunks;
|
||||
uint32_t chunk_prng = i_;
|
||||
for (lfs_size_t j = 0; j < CHUNK_SIZE; j++) {
|
||||
buffer[j] = BENCH_PRNG(&chunk_prng);
|
||||
}
|
||||
|
||||
lfs_file_seek(&lfs, &file, i_*CHUNK_SIZE, LFS_SEEK_SET)
|
||||
=> i_*CHUNK_SIZE;
|
||||
lfs_file_write(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
}
|
||||
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
@@ -0,0 +1,56 @@
|
||||
[cases.bench_superblocks_found]
|
||||
# support benchmarking with files
|
||||
defines.N = [0, 1024]
|
||||
defines.FILE_SIZE = 8
|
||||
defines.CHUNK_SIZE = 8
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
|
||||
// create files?
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
char name[256];
|
||||
uint8_t buffer[CHUNK_SIZE];
|
||||
for (lfs_size_t i = 0; i < N; i++) {
|
||||
sprintf(name, "file%08x", i);
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, name,
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0;
|
||||
|
||||
for (lfs_size_t j = 0; j < FILE_SIZE; j += CHUNK_SIZE) {
|
||||
for (lfs_size_t k = 0; k < CHUNK_SIZE; k++) {
|
||||
buffer[k] = i+j+k;
|
||||
}
|
||||
lfs_file_write(&lfs, &file, buffer, CHUNK_SIZE) => CHUNK_SIZE;
|
||||
}
|
||||
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
}
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
BENCH_START();
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
BENCH_STOP();
|
||||
|
||||
lfs_unmount(&lfs) => 0;
|
||||
'''
|
||||
|
||||
[cases.bench_superblocks_missing]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
|
||||
BENCH_START();
|
||||
int err = lfs_mount(&lfs, cfg);
|
||||
assert(err != 0);
|
||||
BENCH_STOP();
|
||||
'''
|
||||
|
||||
[cases.bench_superblocks_format]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
|
||||
BENCH_START();
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
BENCH_STOP();
|
||||
'''
|
||||
|
||||
Vendored
+977
@@ -0,0 +1,977 @@
|
||||
#include <rtdevice.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include <dfs_file.h>
|
||||
#include <dfs_fs.h>
|
||||
|
||||
#include "lfs.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(RT_VERSION_CHECK) && (RTTHREAD_VERSION >= RT_VERSION_CHECK(5, 0, 2))
|
||||
#define DFS_LFS_RW_RETURN_TYPE ssize_t
|
||||
#define DFS_LFS_LSK_RETURN_TYPE off_t
|
||||
#define DFS_LFS_MKFS(dev_id, fs_name) _dfs_lfs_mkfs(dev_id, fs_name)
|
||||
#else
|
||||
#define DFS_LFS_RW_RETURN_TYPE int
|
||||
#define DFS_LFS_LSK_RETURN_TYPE int
|
||||
#define DFS_LFS_MKFS(dev_id, fs_name) _dfs_lfs_mkfs(dev_id)
|
||||
#endif
|
||||
|
||||
#ifndef RT_DEF_LFS_DRIVERS
|
||||
#define RT_DEF_LFS_DRIVERS 1
|
||||
#endif
|
||||
|
||||
#if (RT_DEF_LFS_DRIVERS < 1)
|
||||
#error "#define RT_DEF_LFS_DRIVERS must > 0"
|
||||
#endif
|
||||
|
||||
#ifndef LFS_READ_SIZE
|
||||
#define LFS_READ_SIZE 256
|
||||
#endif
|
||||
|
||||
#ifndef LFS_PROG_SIZE
|
||||
#define LFS_PROG_SIZE 256
|
||||
#endif
|
||||
|
||||
#ifndef LFS_BLOCK_SIZE
|
||||
#define LFS_BLOCK_SIZE 4096
|
||||
#endif
|
||||
|
||||
#ifndef LFS_CACHE_SIZE
|
||||
#define LFS_CACHE_SIZE LFS_PROG_SIZE
|
||||
#endif
|
||||
|
||||
#ifndef LFS_BLOCK_CYCLES
|
||||
#define LFS_BLOCK_CYCLES (-1)
|
||||
#endif
|
||||
|
||||
#ifndef LFS_LOOKAHEAD_MAX
|
||||
#define LFS_LOOKAHEAD_MAX 128
|
||||
#endif
|
||||
|
||||
#define ATTR_TIMESTAMP 0x74
|
||||
|
||||
typedef struct _dfs_lfs_s
|
||||
{
|
||||
struct lfs lfs;
|
||||
struct lfs_config cfg;
|
||||
struct rt_mutex lock;
|
||||
} dfs_lfs_t;
|
||||
|
||||
typedef struct _dfs_lfs_fd_s
|
||||
{
|
||||
struct lfs* lfs;
|
||||
union
|
||||
{
|
||||
struct lfs_file file;
|
||||
struct lfs_dir dir;
|
||||
} u;
|
||||
} dfs_lfs_fd_t;
|
||||
|
||||
static struct _dfs_lfs_s* _lfs_mount_tbl[RT_DEF_LFS_DRIVERS] = {0};
|
||||
|
||||
#ifdef LFS_THREADSAFE
|
||||
// Lock the underlying block device. Negative error codes
|
||||
// are propogated to the user.
|
||||
int _lfs_lock(const struct lfs_config *c)
|
||||
{
|
||||
dfs_lfs_t *dfs_lfs = rt_container_of(c, dfs_lfs_t, cfg);
|
||||
|
||||
if (rt_mutex_take(&dfs_lfs->lock, RT_WAITING_FOREVER) != RT_EOK)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Unlock the underlying block device. Negative error codes
|
||||
// are propogated to the user.
|
||||
int _lfs_unlock(const struct lfs_config *c)
|
||||
{
|
||||
dfs_lfs_t *dfs_lfs = rt_container_of(c, dfs_lfs_t, cfg);
|
||||
|
||||
if (rt_mutex_release(&dfs_lfs->lock) != RT_EOK)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Read a region in a block. Negative error codes are propogated
|
||||
// to the user.
|
||||
static int _lfs_flash_read(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, void* buffer, lfs_size_t size)
|
||||
{
|
||||
struct rt_mtd_nor_device* mtd_nor;
|
||||
|
||||
RT_ASSERT(c != RT_NULL);
|
||||
RT_ASSERT(c->context != RT_NULL);
|
||||
|
||||
mtd_nor = (struct rt_mtd_nor_device*)c->context;
|
||||
if (rt_mtd_nor_read(mtd_nor, block * c->block_size + off, buffer, size) != size)
|
||||
{
|
||||
return LFS_ERR_IO;
|
||||
}
|
||||
|
||||
return LFS_ERR_OK;
|
||||
}
|
||||
|
||||
// Program a region in a block. The block must have previously
|
||||
// been erased. Negative error codes are propogated to the user.
|
||||
// May return LFS_ERR_CORRUPT if the block should be considered bad.
|
||||
static int _lfs_flash_prog(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, const void* buffer, lfs_size_t size)
|
||||
{
|
||||
struct rt_mtd_nor_device* mtd_nor;
|
||||
|
||||
RT_ASSERT(c != RT_NULL);
|
||||
RT_ASSERT(c->context != RT_NULL);
|
||||
|
||||
mtd_nor = (struct rt_mtd_nor_device*)c->context;
|
||||
if (rt_mtd_nor_write(mtd_nor, block * c->block_size + off, buffer, size) != size)
|
||||
{
|
||||
return LFS_ERR_IO;
|
||||
}
|
||||
|
||||
return LFS_ERR_OK;
|
||||
}
|
||||
|
||||
// Erase a block. A block must be erased before being programmed.
|
||||
// The state of an erased block is undefined. Negative error codes
|
||||
// are propogated to the user.
|
||||
// May return LFS_ERR_CORRUPT if the block should be considered bad.
|
||||
static int _lfs_flash_erase(const struct lfs_config* c, lfs_block_t block)
|
||||
{
|
||||
struct rt_mtd_nor_device* mtd_nor;
|
||||
|
||||
RT_ASSERT(c != RT_NULL);
|
||||
RT_ASSERT(c->context != RT_NULL);
|
||||
|
||||
mtd_nor = (struct rt_mtd_nor_device*)c->context;
|
||||
if (rt_mtd_nor_erase_block(mtd_nor, block * c->block_size, c->block_size) != RT_EOK)
|
||||
{
|
||||
return LFS_ERR_IO;
|
||||
}
|
||||
|
||||
return LFS_ERR_OK;
|
||||
}
|
||||
|
||||
// Sync the state of the underlying block device. Negative error codes
|
||||
// are propogated to the user.
|
||||
static int _lfs_flash_sync(const struct lfs_config* c)
|
||||
{
|
||||
return LFS_ERR_OK;
|
||||
}
|
||||
|
||||
/* results:
|
||||
* -1, no space to install fatfs driver
|
||||
* >= 0, there is an space to install littlefs driver
|
||||
*/
|
||||
static int _get_disk(rt_device_t dev_id)
|
||||
{
|
||||
int index;
|
||||
|
||||
if (dev_id == RT_NULL)
|
||||
{
|
||||
for (index = 0; index < RT_DEF_LFS_DRIVERS; index ++)
|
||||
{
|
||||
if(_lfs_mount_tbl[index] == RT_NULL)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (index = 0; index < RT_DEF_LFS_DRIVERS; index ++)
|
||||
{
|
||||
if ((_lfs_mount_tbl[index] != RT_NULL) && (_lfs_mount_tbl[index]->cfg.context == (void *)dev_id))
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _lfs_result_to_dfs(int result)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case LFS_ERR_OK:
|
||||
break;
|
||||
|
||||
case LFS_ERR_IO:
|
||||
status = -EIO;
|
||||
break; // Error during device operation
|
||||
|
||||
case LFS_ERR_NOENT:
|
||||
status = -ENOENT;
|
||||
break; // No directory entry
|
||||
|
||||
case LFS_ERR_EXIST:
|
||||
status = -EEXIST;
|
||||
break; // Entry already exists
|
||||
|
||||
case LFS_ERR_NOTDIR:
|
||||
status = -ENOTDIR;
|
||||
break; // Entry is not a dir
|
||||
|
||||
case LFS_ERR_ISDIR:
|
||||
status = -EISDIR;
|
||||
break; // Entry is a dir
|
||||
|
||||
case LFS_ERR_NOTEMPTY:
|
||||
status = -ENOTEMPTY;
|
||||
break; // Dir is not empty
|
||||
|
||||
case LFS_ERR_BADF:
|
||||
status = -EBADF;
|
||||
break; // Bad file number
|
||||
|
||||
case LFS_ERR_INVAL:
|
||||
status = -EINVAL;
|
||||
break; // Invalid parameter
|
||||
|
||||
case LFS_ERR_NOSPC:
|
||||
status = -ENOSPC;
|
||||
break; // No space left on device
|
||||
|
||||
case LFS_ERR_NOMEM:
|
||||
status = -ENOMEM;
|
||||
break; // No more memory available
|
||||
|
||||
case LFS_ERR_CORRUPT:
|
||||
status = -52;
|
||||
break; // Corrupted
|
||||
|
||||
default:
|
||||
status = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void _lfs_load_config(struct lfs_config* lfs_cfg, struct rt_mtd_nor_device* mtd_nor)
|
||||
{
|
||||
uint64_t mtd_size;
|
||||
|
||||
lfs_cfg->context = (void*)mtd_nor;
|
||||
|
||||
lfs_cfg->read_size = LFS_READ_SIZE;
|
||||
lfs_cfg->prog_size = LFS_PROG_SIZE;
|
||||
|
||||
lfs_cfg->block_size = mtd_nor->block_size;
|
||||
if (lfs_cfg->block_size < LFS_BLOCK_SIZE)
|
||||
{
|
||||
lfs_cfg->block_size = LFS_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
lfs_cfg->cache_size = LFS_CACHE_SIZE;
|
||||
lfs_cfg->block_cycles = LFS_BLOCK_CYCLES;
|
||||
|
||||
mtd_size = mtd_nor->block_end - mtd_nor->block_start;
|
||||
mtd_size *= mtd_nor->block_size;
|
||||
lfs_cfg->block_count = mtd_size / lfs_cfg->block_size;
|
||||
|
||||
lfs_cfg->lookahead_size = 32 * ((lfs_cfg->block_count + 31) / 32);
|
||||
if (lfs_cfg->lookahead_size > LFS_LOOKAHEAD_MAX)
|
||||
{
|
||||
lfs_cfg->lookahead_size = LFS_LOOKAHEAD_MAX;
|
||||
}
|
||||
#ifdef LFS_THREADSAFE
|
||||
lfs_cfg->lock = _lfs_lock;
|
||||
lfs_cfg->unlock = _lfs_unlock;
|
||||
#endif
|
||||
lfs_cfg->read = _lfs_flash_read;
|
||||
lfs_cfg->prog = _lfs_flash_prog;
|
||||
lfs_cfg->erase = _lfs_flash_erase;
|
||||
lfs_cfg->sync = _lfs_flash_sync;
|
||||
}
|
||||
|
||||
static int _dfs_lfs_mount(struct dfs_filesystem* dfs, unsigned long rwflag, const void* data)
|
||||
{
|
||||
int result;
|
||||
int index;
|
||||
dfs_lfs_t* dfs_lfs;
|
||||
|
||||
/* Check Device Type */
|
||||
if (dfs->dev_id->type != RT_Device_Class_MTD)
|
||||
{
|
||||
rt_kprintf("The flash device type must be MTD!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* get an empty position */
|
||||
index = _get_disk(RT_NULL);
|
||||
if (index == -1)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*create lfs handle */
|
||||
dfs_lfs = (dfs_lfs_t*)rt_malloc(sizeof(dfs_lfs_t));
|
||||
if (dfs_lfs == RT_NULL)
|
||||
{
|
||||
rt_kprintf("ERROR:no memory!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
rt_memset(dfs_lfs, 0, sizeof(dfs_lfs_t));
|
||||
rt_mutex_init(&dfs_lfs->lock, "lfslock", RT_IPC_FLAG_PRIO);
|
||||
_lfs_load_config(&dfs_lfs->cfg, (struct rt_mtd_nor_device*)dfs->dev_id);
|
||||
|
||||
/* mount lfs*/
|
||||
result = lfs_mount(&dfs_lfs->lfs, &dfs_lfs->cfg);
|
||||
if (result != LFS_ERR_OK)
|
||||
{
|
||||
rt_mutex_detach(&dfs_lfs->lock);
|
||||
/* release memory */
|
||||
rt_free(dfs_lfs);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* mount succeed! */
|
||||
dfs->data = (void*)dfs_lfs;
|
||||
_lfs_mount_tbl[index] = dfs_lfs;
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static int _dfs_lfs_unmount(struct dfs_filesystem* dfs)
|
||||
{
|
||||
int result;
|
||||
int index;
|
||||
dfs_lfs_t* dfs_lfs;
|
||||
|
||||
RT_ASSERT(dfs != RT_NULL);
|
||||
RT_ASSERT(dfs->data != RT_NULL);
|
||||
|
||||
/* find the device index and then umount it */
|
||||
index = _get_disk(dfs->dev_id);
|
||||
if (index == -1)
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
_lfs_mount_tbl[index] = RT_NULL;
|
||||
|
||||
dfs_lfs = (dfs_lfs_t*)dfs->data;
|
||||
dfs->data = RT_NULL;
|
||||
|
||||
result = lfs_unmount(&dfs_lfs->lfs);
|
||||
rt_mutex_detach(&dfs_lfs->lock);
|
||||
rt_free(dfs_lfs);
|
||||
|
||||
return _lfs_result_to_dfs(result);
|
||||
}
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
static int DFS_LFS_MKFS(rt_device_t dev_id, const char *fs_name)
|
||||
{
|
||||
int result;
|
||||
int index;
|
||||
dfs_lfs_t* dfs_lfs;
|
||||
|
||||
if (dev_id == RT_NULL)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Check Device Type */
|
||||
if (dev_id->type != RT_Device_Class_MTD)
|
||||
{
|
||||
rt_kprintf("The flash device type must be MTD!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
index = _get_disk(dev_id);
|
||||
if (index == -1)
|
||||
{
|
||||
/* create lfs handle */
|
||||
dfs_lfs = rt_malloc(sizeof(dfs_lfs_t));
|
||||
if (dfs_lfs == RT_NULL)
|
||||
{
|
||||
rt_kprintf("ERROR:no memory!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
rt_memset(dfs_lfs, 0, sizeof(dfs_lfs_t));
|
||||
rt_mutex_init(&dfs_lfs->lock, "lfslock", RT_IPC_FLAG_PRIO);
|
||||
_lfs_load_config(&dfs_lfs->cfg, (struct rt_mtd_nor_device*)dev_id);
|
||||
|
||||
/* format flash device */
|
||||
result = lfs_format(&dfs_lfs->lfs, &dfs_lfs->cfg);
|
||||
rt_mutex_detach(&dfs_lfs->lock);
|
||||
rt_free(dfs_lfs);
|
||||
return _lfs_result_to_dfs(result);
|
||||
}
|
||||
|
||||
dfs_lfs = _lfs_mount_tbl[index];
|
||||
|
||||
/* unmount it */
|
||||
result = lfs_unmount(&dfs_lfs->lfs);
|
||||
if (result != LFS_ERR_OK)
|
||||
{
|
||||
return _lfs_result_to_dfs(result);
|
||||
}
|
||||
|
||||
_lfs_mount_tbl[index] = RT_NULL;
|
||||
|
||||
/* format flash device */
|
||||
result = lfs_format(&dfs_lfs->lfs, &dfs_lfs->cfg);
|
||||
if (result != LFS_ERR_OK)
|
||||
{
|
||||
return _lfs_result_to_dfs(result);
|
||||
}
|
||||
|
||||
_lfs_load_config(&dfs_lfs->cfg, (struct rt_mtd_nor_device*)dev_id);
|
||||
|
||||
/* mount lfs*/
|
||||
result = lfs_mount(&dfs_lfs->lfs, &dfs_lfs->cfg);
|
||||
if (result == LFS_ERR_OK)
|
||||
{
|
||||
_lfs_mount_tbl[index] = dfs_lfs;
|
||||
}
|
||||
|
||||
return _lfs_result_to_dfs(result);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _dfs_lfs_statfs_count(void* p, lfs_block_t b)
|
||||
{
|
||||
*(lfs_size_t*)p += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _dfs_lfs_statfs(struct dfs_filesystem* dfs, struct statfs* buf)
|
||||
{
|
||||
dfs_lfs_t* dfs_lfs;
|
||||
int result;
|
||||
lfs_size_t in_use = 0;
|
||||
|
||||
RT_ASSERT(buf != RT_NULL);
|
||||
RT_ASSERT(dfs != RT_NULL);
|
||||
RT_ASSERT(dfs->data != RT_NULL);
|
||||
|
||||
dfs_lfs = (dfs_lfs_t*)dfs->data;
|
||||
|
||||
/* Get total sectors and free sectors */
|
||||
result = lfs_fs_traverse(&dfs_lfs->lfs, _dfs_lfs_statfs_count, &in_use);
|
||||
if (result != LFS_ERR_OK)
|
||||
{
|
||||
return _lfs_result_to_dfs(result);
|
||||
}
|
||||
|
||||
buf->f_bsize = dfs_lfs->cfg.block_size;
|
||||
buf->f_blocks = dfs_lfs->cfg.block_count;
|
||||
buf->f_bfree = dfs_lfs->cfg.block_count - in_use;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
static int _dfs_lfs_unlink(struct dfs_filesystem* dfs, const char* path)
|
||||
{
|
||||
dfs_lfs_t* dfs_lfs;
|
||||
int result;
|
||||
|
||||
RT_ASSERT(dfs != RT_NULL);
|
||||
RT_ASSERT(dfs->data != RT_NULL);
|
||||
|
||||
dfs_lfs = (dfs_lfs_t*)dfs->data;
|
||||
result = lfs_remove(&dfs_lfs->lfs, path);
|
||||
|
||||
return _lfs_result_to_dfs(result);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void _dfs_lfs_tostat(struct stat* st, struct lfs_info* info, time_t mtime)
|
||||
{
|
||||
memset(st, 0, sizeof(struct stat));
|
||||
|
||||
/* convert to dfs stat structure */
|
||||
st->st_dev = 0;
|
||||
st->st_size = info->size;
|
||||
st->st_mode = S_IRWXU | S_IRWXG | S_IRWXO;
|
||||
|
||||
switch (info->type)
|
||||
{
|
||||
case LFS_TYPE_DIR:
|
||||
st->st_mode |= S_IFDIR;
|
||||
break;
|
||||
|
||||
case LFS_TYPE_REG:
|
||||
st->st_mode |= S_IFREG;
|
||||
break;
|
||||
}
|
||||
|
||||
st->st_mtime = mtime;
|
||||
}
|
||||
|
||||
static int _dfs_lfs_stat(struct dfs_filesystem* dfs, const char* path, struct stat* st)
|
||||
{
|
||||
dfs_lfs_t* dfs_lfs;
|
||||
int result;
|
||||
struct lfs_info info;
|
||||
|
||||
RT_ASSERT(dfs != RT_NULL);
|
||||
RT_ASSERT(dfs->data != RT_NULL);
|
||||
|
||||
dfs_lfs = (dfs_lfs_t*)dfs->data;
|
||||
result = lfs_stat(&dfs_lfs->lfs, path, &info);
|
||||
|
||||
if (result != LFS_ERR_OK)
|
||||
{
|
||||
return _lfs_result_to_dfs(result);
|
||||
}
|
||||
|
||||
time_t mtime = 0;
|
||||
lfs_getattr(&dfs_lfs->lfs, path, ATTR_TIMESTAMP, &mtime, sizeof(time_t));
|
||||
|
||||
_dfs_lfs_tostat(st, &info, mtime);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
static int _dfs_lfs_rename(struct dfs_filesystem* dfs, const char* from, const char* to)
|
||||
{
|
||||
dfs_lfs_t* dfs_lfs;
|
||||
int result;
|
||||
|
||||
RT_ASSERT(dfs != RT_NULL);
|
||||
RT_ASSERT(dfs->data != RT_NULL);
|
||||
|
||||
dfs_lfs = (dfs_lfs_t*)dfs->data;
|
||||
result = lfs_rename(&dfs_lfs->lfs, from, to);
|
||||
|
||||
return _lfs_result_to_dfs(result);
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* file operations
|
||||
******************************************************************************/
|
||||
static int _dfs_lfs_open(struct dfs_file* file)
|
||||
{
|
||||
struct dfs_filesystem* dfs;
|
||||
dfs_lfs_t* dfs_lfs;
|
||||
int result;
|
||||
int flags = 0;
|
||||
|
||||
RT_ASSERT(file != RT_NULL);
|
||||
|
||||
dfs = (struct dfs_filesystem*)file->vnode->fs;
|
||||
|
||||
RT_ASSERT(file->vnode->ref_count > 0);
|
||||
if (file->vnode->ref_count > 1)
|
||||
{
|
||||
if (file->vnode->type == FT_DIRECTORY
|
||||
&& !(file->flags & O_DIRECTORY))
|
||||
{
|
||||
return -ENOENT;
|
||||
}
|
||||
file->pos = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dfs_lfs = (dfs_lfs_t*)dfs->data;
|
||||
|
||||
if (file->flags & O_DIRECTORY)
|
||||
{
|
||||
dfs_lfs_fd_t* dfs_lfs_fd = rt_malloc(sizeof(dfs_lfs_fd_t));
|
||||
if (dfs_lfs_fd == RT_NULL)
|
||||
{
|
||||
rt_kprintf("ERROR:no memory!\n");
|
||||
result = -ENOMEM;
|
||||
|
||||
goto _error_dir;
|
||||
}
|
||||
rt_memset(dfs_lfs_fd, 0, sizeof(dfs_lfs_fd_t));
|
||||
dfs_lfs_fd->lfs = &dfs_lfs->lfs;
|
||||
|
||||
if (file->flags & O_CREAT)
|
||||
{
|
||||
#ifndef LFS_READONLY
|
||||
result = lfs_mkdir(dfs_lfs_fd->lfs, file->vnode->path);
|
||||
#else
|
||||
result = -EINVAL;
|
||||
#endif
|
||||
if (result != LFS_ERR_OK)
|
||||
{
|
||||
goto _error_dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
time_t now = time(RT_NULL);
|
||||
lfs_setattr(dfs_lfs_fd->lfs, file->vnode->path, ATTR_TIMESTAMP, &now, sizeof(time_t));
|
||||
}
|
||||
}
|
||||
|
||||
result = lfs_dir_open(dfs_lfs_fd->lfs, &dfs_lfs_fd->u.dir, file->vnode->path);
|
||||
if (result != LFS_ERR_OK)
|
||||
{
|
||||
goto _error_dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
file->data = (void*)dfs_lfs_fd;
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
_error_dir:
|
||||
if (dfs_lfs_fd != RT_NULL)
|
||||
{
|
||||
rt_free(dfs_lfs_fd);
|
||||
}
|
||||
|
||||
return _lfs_result_to_dfs(result);
|
||||
}
|
||||
else
|
||||
{
|
||||
dfs_lfs_fd_t* dfs_lfs_fd = rt_malloc(sizeof(dfs_lfs_fd_t));
|
||||
if (dfs_lfs_fd == RT_NULL)
|
||||
{
|
||||
rt_kprintf("ERROR:no memory!\n");
|
||||
result = -ENOMEM;
|
||||
|
||||
goto _error_file;
|
||||
}
|
||||
rt_memset(dfs_lfs_fd, 0, sizeof(dfs_lfs_fd_t));
|
||||
dfs_lfs_fd->lfs = &dfs_lfs->lfs;
|
||||
|
||||
if ((file->flags & 3) == O_RDONLY)
|
||||
flags |= LFS_O_RDONLY;
|
||||
if ((file->flags & 3) == O_WRONLY)
|
||||
flags |= LFS_O_WRONLY;
|
||||
if ((file->flags & 3) == O_RDWR)
|
||||
flags |= LFS_O_RDWR;
|
||||
if (file->flags & O_CREAT)
|
||||
flags |= LFS_O_CREAT;
|
||||
if (file->flags & O_EXCL)
|
||||
flags |= LFS_O_EXCL;
|
||||
if (file->flags & O_TRUNC)
|
||||
flags |= LFS_O_TRUNC;
|
||||
if (file->flags & O_APPEND)
|
||||
flags |= LFS_O_APPEND;
|
||||
|
||||
result = lfs_file_open(dfs_lfs_fd->lfs, &dfs_lfs_fd->u.file, file->vnode->path, flags);
|
||||
if (result != LFS_ERR_OK)
|
||||
{
|
||||
goto _error_file;
|
||||
}
|
||||
else
|
||||
{
|
||||
file->data = (void*)dfs_lfs_fd;
|
||||
file->pos = dfs_lfs_fd->u.file.pos;
|
||||
file->vnode->size = dfs_lfs_fd->u.file.ctz.size;
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
_error_file:
|
||||
if (dfs_lfs_fd != RT_NULL)
|
||||
{
|
||||
rt_free(dfs_lfs_fd);
|
||||
}
|
||||
|
||||
return _lfs_result_to_dfs(result);
|
||||
}
|
||||
}
|
||||
|
||||
static int _dfs_lfs_close(struct dfs_file* file)
|
||||
{
|
||||
int result;
|
||||
dfs_lfs_fd_t* dfs_lfs_fd;
|
||||
uint8_t need_time_update;
|
||||
RT_ASSERT(file != RT_NULL);
|
||||
RT_ASSERT(file->data != RT_NULL);
|
||||
|
||||
RT_ASSERT(file->vnode->ref_count > 0);
|
||||
if (file->vnode->ref_count > 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
dfs_lfs_fd = (dfs_lfs_fd_t*)file->data;
|
||||
|
||||
if (file->vnode->type == FT_DIRECTORY)
|
||||
{
|
||||
result = lfs_dir_close(dfs_lfs_fd->lfs, &dfs_lfs_fd->u.dir);
|
||||
}
|
||||
else
|
||||
{
|
||||
need_time_update = (dfs_lfs_fd->u.file.flags & LFS_F_DIRTY) || (dfs_lfs_fd->u.file.flags & LFS_F_WRITING);
|
||||
result = lfs_file_close(dfs_lfs_fd->lfs, &dfs_lfs_fd->u.file);
|
||||
if (result == LFS_ERR_OK && need_time_update)
|
||||
{
|
||||
time_t now = time(RT_NULL);
|
||||
lfs_setattr(dfs_lfs_fd->lfs, file->vnode->path, ATTR_TIMESTAMP, &now, sizeof(time_t));
|
||||
}
|
||||
}
|
||||
|
||||
rt_free(dfs_lfs_fd);
|
||||
|
||||
return _lfs_result_to_dfs(result);
|
||||
}
|
||||
|
||||
static int _dfs_lfs_ioctl(struct dfs_file* file, int cmd, void* args)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static DFS_LFS_RW_RETURN_TYPE _dfs_lfs_read(struct dfs_file* file, void* buf, size_t len)
|
||||
{
|
||||
lfs_ssize_t ssize;
|
||||
dfs_lfs_fd_t* dfs_lfs_fd;
|
||||
|
||||
RT_ASSERT(file != RT_NULL);
|
||||
RT_ASSERT(file->data != RT_NULL);
|
||||
|
||||
if (file->vnode->type == FT_DIRECTORY)
|
||||
{
|
||||
return -EISDIR;
|
||||
}
|
||||
|
||||
dfs_lfs_fd = (dfs_lfs_fd_t*)file->data;
|
||||
|
||||
#if 0
|
||||
if (lfs_file_tell(dfs_lfs_fd->lfs, &dfs_lfs_fd->u.file) != file->pos)
|
||||
{
|
||||
lfs_soff_t soff = lfs_file_seek(dfs_lfs_fd->lfs, &dfs_lfs_fd->u.file, file->pos, LFS_SEEK_SET);
|
||||
if (soff < 0)
|
||||
{
|
||||
return _lfs_result_to_dfs(soff);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ssize = lfs_file_read(dfs_lfs_fd->lfs, &dfs_lfs_fd->u.file, buf, len);
|
||||
if (ssize < 0)
|
||||
{
|
||||
return _lfs_result_to_dfs(ssize);
|
||||
}
|
||||
|
||||
/* update position */
|
||||
file->pos = dfs_lfs_fd->u.file.pos;
|
||||
|
||||
return ssize;
|
||||
}
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
static DFS_LFS_RW_RETURN_TYPE _dfs_lfs_write(struct dfs_file* file, const void* buf, size_t len)
|
||||
{
|
||||
lfs_ssize_t ssize;
|
||||
dfs_lfs_fd_t* dfs_lfs_fd;
|
||||
RT_ASSERT(file != RT_NULL);
|
||||
RT_ASSERT(file->data != RT_NULL);
|
||||
|
||||
if (file->vnode->type == FT_DIRECTORY)
|
||||
{
|
||||
return -EISDIR;
|
||||
}
|
||||
|
||||
dfs_lfs_fd = (dfs_lfs_fd_t*)file->data;
|
||||
|
||||
#if 0
|
||||
if (lfs_file_tell(dfs_lfs_fd->lfs, &dfs_lfs_fd->u.file) != file->pos)
|
||||
{
|
||||
lfs_soff_t soff = lfs_file_seek(dfs_lfs_fd->lfs, &dfs_lfs_fd->u.file, file->pos, LFS_SEEK_SET);
|
||||
if (soff < 0)
|
||||
{
|
||||
return _lfs_result_to_dfs(soff);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ssize = lfs_file_write(dfs_lfs_fd->lfs, &dfs_lfs_fd->u.file, buf, len);
|
||||
if (ssize < 0)
|
||||
{
|
||||
return _lfs_result_to_dfs(ssize);
|
||||
}
|
||||
|
||||
/* update position and file size */
|
||||
file->pos = dfs_lfs_fd->u.file.pos;
|
||||
file->vnode->size = dfs_lfs_fd->u.file.ctz.size;
|
||||
|
||||
return ssize;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int _dfs_lfs_flush(struct dfs_file* file)
|
||||
{
|
||||
int result;
|
||||
dfs_lfs_fd_t* dfs_lfs_fd;
|
||||
uint8_t need_time_update;
|
||||
|
||||
RT_ASSERT(file != RT_NULL);
|
||||
RT_ASSERT(file->data != RT_NULL);
|
||||
|
||||
dfs_lfs_fd = (dfs_lfs_fd_t*)file->data;
|
||||
need_time_update = (dfs_lfs_fd->u.file.flags & LFS_F_DIRTY) || (dfs_lfs_fd->u.file.flags & LFS_F_WRITING);
|
||||
result = lfs_file_sync(dfs_lfs_fd->lfs, &dfs_lfs_fd->u.file);
|
||||
if (result == LFS_ERR_OK && need_time_update)
|
||||
{
|
||||
time_t now = time(RT_NULL);
|
||||
lfs_setattr(dfs_lfs_fd->lfs, file->vnode->path, ATTR_TIMESTAMP, &now, sizeof(time_t));
|
||||
}
|
||||
|
||||
return _lfs_result_to_dfs(result);
|
||||
}
|
||||
|
||||
static DFS_LFS_LSK_RETURN_TYPE _dfs_lfs_lseek(struct dfs_file* file, rt_off_t offset)
|
||||
{
|
||||
dfs_lfs_fd_t* dfs_lfs_fd;
|
||||
|
||||
RT_ASSERT(file != RT_NULL);
|
||||
RT_ASSERT(file->data != RT_NULL);
|
||||
|
||||
dfs_lfs_fd = (dfs_lfs_fd_t*)file->data;
|
||||
|
||||
if (file->vnode->type == FT_REGULAR)
|
||||
{
|
||||
lfs_soff_t soff = lfs_file_seek(dfs_lfs_fd->lfs, &dfs_lfs_fd->u.file, offset, LFS_SEEK_SET);
|
||||
if (soff < 0)
|
||||
{
|
||||
return _lfs_result_to_dfs(soff);
|
||||
}
|
||||
|
||||
file->pos = dfs_lfs_fd->u.file.pos;
|
||||
}
|
||||
else if (file->vnode->type == FT_DIRECTORY)
|
||||
{
|
||||
lfs_soff_t soff = lfs_dir_seek(dfs_lfs_fd->lfs, &dfs_lfs_fd->u.dir, offset);
|
||||
if (soff < 0)
|
||||
{
|
||||
return _lfs_result_to_dfs(soff);
|
||||
}
|
||||
|
||||
file->pos = dfs_lfs_fd->u.dir.pos;
|
||||
}
|
||||
|
||||
return (file->pos);
|
||||
}
|
||||
|
||||
static int _dfs_lfs_getdents(struct dfs_file* file, struct dirent* dirp, uint32_t count)
|
||||
{
|
||||
dfs_lfs_fd_t* dfs_lfs_fd;
|
||||
int result;
|
||||
int index;
|
||||
struct dirent* d;
|
||||
struct lfs_info info;
|
||||
|
||||
RT_ASSERT(file->data != RT_NULL);
|
||||
|
||||
dfs_lfs_fd = (dfs_lfs_fd_t*)(file->data);
|
||||
|
||||
/* make integer count */
|
||||
count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
|
||||
if (count == 0)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
while (1)
|
||||
{
|
||||
d = dirp + index;
|
||||
|
||||
result = lfs_dir_read(dfs_lfs_fd->lfs, &dfs_lfs_fd->u.dir, &info);
|
||||
if ((result != 1) || (info.name[0] == 0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (rt_strcmp(info.name, ".") == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (rt_strcmp(info.name, "..") == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
d->d_type = DT_UNKNOWN;
|
||||
|
||||
switch (info.type)
|
||||
{
|
||||
case LFS_TYPE_DIR:
|
||||
d->d_type |= DT_DIR;
|
||||
break;
|
||||
|
||||
case LFS_TYPE_REG:
|
||||
d->d_type |= DT_REG;
|
||||
break;
|
||||
}
|
||||
|
||||
d->d_namlen = (rt_uint8_t)rt_strlen(info.name);
|
||||
d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
|
||||
rt_strncpy(d->d_name, info.name, DFS_PATH_MAX);
|
||||
|
||||
index++;
|
||||
if (index * sizeof(struct dirent) >= count)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == 0)
|
||||
{
|
||||
return _lfs_result_to_dfs(result);
|
||||
}
|
||||
|
||||
file->pos += index * sizeof(struct dirent);
|
||||
|
||||
return index * sizeof(struct dirent);
|
||||
}
|
||||
|
||||
static const struct dfs_file_ops _dfs_lfs_fops = {
|
||||
_dfs_lfs_open,
|
||||
_dfs_lfs_close,
|
||||
_dfs_lfs_ioctl,
|
||||
_dfs_lfs_read,
|
||||
#ifndef LFS_READONLY
|
||||
_dfs_lfs_write,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
_dfs_lfs_flush,
|
||||
_dfs_lfs_lseek,
|
||||
_dfs_lfs_getdents,
|
||||
// RT_NULL, /* poll interface */
|
||||
};
|
||||
|
||||
static const struct dfs_filesystem_ops _dfs_lfs_ops = {
|
||||
"lfs",
|
||||
DFS_FS_FLAG_DEFAULT,
|
||||
&_dfs_lfs_fops,
|
||||
_dfs_lfs_mount,
|
||||
_dfs_lfs_unmount,
|
||||
#ifndef LFS_READONLY
|
||||
_dfs_lfs_mkfs,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
_dfs_lfs_statfs,
|
||||
#ifndef LFS_READONLY
|
||||
_dfs_lfs_unlink,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
_dfs_lfs_stat,
|
||||
#ifndef LFS_READONLY
|
||||
_dfs_lfs_rename,
|
||||
#else
|
||||
NULL,
|
||||
#endif
|
||||
};
|
||||
|
||||
int dfs_lfs_init(void)
|
||||
{
|
||||
/* register ram file system */
|
||||
return dfs_register(&_dfs_lfs_ops);
|
||||
}
|
||||
INIT_COMPONENT_EXPORT(dfs_lfs_init);
|
||||
Vendored
+6549
File diff suppressed because it is too large.
Load diff
Vendored
+801
@@ -0,0 +1,801 @@
|
||||
/*
|
||||
* The little filesystem
|
||||
*
|
||||
* Copyright (c) 2022, The littlefs authors.
|
||||
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef LFS_H
|
||||
#define LFS_H
|
||||
|
||||
#include "lfs_util.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
/// Version info ///
|
||||
|
||||
// Software library version
|
||||
// Major (top-nibble), incremented on backwards incompatible changes
|
||||
// Minor (bottom-nibble), incremented on feature additions
|
||||
#define LFS_VERSION 0x0002000b
|
||||
#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
|
||||
#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))
|
||||
|
||||
// Version of On-disk data structures
|
||||
// Major (top-nibble), incremented on backwards incompatible changes
|
||||
// Minor (bottom-nibble), incremented on feature additions
|
||||
#define LFS_DISK_VERSION 0x00020001
|
||||
#define LFS_DISK_VERSION_MAJOR (0xffff & (LFS_DISK_VERSION >> 16))
|
||||
#define LFS_DISK_VERSION_MINOR (0xffff & (LFS_DISK_VERSION >> 0))
|
||||
|
||||
|
||||
/// Definitions ///
|
||||
|
||||
// Type definitions
|
||||
typedef uint32_t lfs_size_t;
|
||||
typedef uint32_t lfs_off_t;
|
||||
|
||||
typedef int32_t lfs_ssize_t;
|
||||
typedef int32_t lfs_soff_t;
|
||||
|
||||
typedef uint32_t lfs_block_t;
|
||||
|
||||
// Maximum name size in bytes, may be redefined to reduce the size of the
|
||||
// info struct. Limited to <= 1022. Stored in superblock and must be
|
||||
// respected by other littlefs drivers.
|
||||
#ifndef LFS_NAME_MAX
|
||||
#define LFS_NAME_MAX 255
|
||||
#endif
|
||||
|
||||
// Maximum size of a file in bytes, may be redefined to limit to support other
|
||||
// drivers. Limited on disk to <= 2147483647. Stored in superblock and must be
|
||||
// respected by other littlefs drivers.
|
||||
#ifndef LFS_FILE_MAX
|
||||
#define LFS_FILE_MAX 2147483647
|
||||
#endif
|
||||
|
||||
// Maximum size of custom attributes in bytes, may be redefined, but there is
|
||||
// no real benefit to using a smaller LFS_ATTR_MAX. Limited to <= 1022. Stored
|
||||
// in superblock and must be respected by other littlefs drivers.
|
||||
#ifndef LFS_ATTR_MAX
|
||||
#define LFS_ATTR_MAX 1022
|
||||
#endif
|
||||
|
||||
// Possible error codes, these are negative to allow
|
||||
// valid positive return values
|
||||
enum lfs_error {
|
||||
LFS_ERR_OK = 0, // No error
|
||||
LFS_ERR_IO = -5, // Error during device operation
|
||||
LFS_ERR_CORRUPT = -84, // Corrupted
|
||||
LFS_ERR_NOENT = -2, // No directory entry
|
||||
LFS_ERR_EXIST = -17, // Entry already exists
|
||||
LFS_ERR_NOTDIR = -20, // Entry is not a dir
|
||||
LFS_ERR_ISDIR = -21, // Entry is a dir
|
||||
LFS_ERR_NOTEMPTY = -39, // Dir is not empty
|
||||
LFS_ERR_BADF = -9, // Bad file number
|
||||
LFS_ERR_FBIG = -27, // File too large
|
||||
LFS_ERR_INVAL = -22, // Invalid parameter
|
||||
LFS_ERR_NOSPC = -28, // No space left on device
|
||||
LFS_ERR_NOMEM = -12, // No more memory available
|
||||
LFS_ERR_NOATTR = -61, // No data/attr available
|
||||
LFS_ERR_NAMETOOLONG = -36, // File name too long
|
||||
};
|
||||
|
||||
// File types
|
||||
enum lfs_type {
|
||||
// file types
|
||||
LFS_TYPE_REG = 0x001,
|
||||
LFS_TYPE_DIR = 0x002,
|
||||
|
||||
// internally used types
|
||||
LFS_TYPE_SPLICE = 0x400,
|
||||
LFS_TYPE_NAME = 0x000,
|
||||
LFS_TYPE_STRUCT = 0x200,
|
||||
LFS_TYPE_USERATTR = 0x300,
|
||||
LFS_TYPE_FROM = 0x100,
|
||||
LFS_TYPE_TAIL = 0x600,
|
||||
LFS_TYPE_GLOBALS = 0x700,
|
||||
LFS_TYPE_CRC = 0x500,
|
||||
|
||||
// internally used type specializations
|
||||
LFS_TYPE_CREATE = 0x401,
|
||||
LFS_TYPE_DELETE = 0x4ff,
|
||||
LFS_TYPE_SUPERBLOCK = 0x0ff,
|
||||
LFS_TYPE_DIRSTRUCT = 0x200,
|
||||
LFS_TYPE_CTZSTRUCT = 0x202,
|
||||
LFS_TYPE_INLINESTRUCT = 0x201,
|
||||
LFS_TYPE_SOFTTAIL = 0x600,
|
||||
LFS_TYPE_HARDTAIL = 0x601,
|
||||
LFS_TYPE_MOVESTATE = 0x7ff,
|
||||
LFS_TYPE_CCRC = 0x500,
|
||||
LFS_TYPE_FCRC = 0x5ff,
|
||||
|
||||
// internal chip sources
|
||||
LFS_FROM_NOOP = 0x000,
|
||||
LFS_FROM_MOVE = 0x101,
|
||||
LFS_FROM_USERATTRS = 0x102,
|
||||
};
|
||||
|
||||
// File open flags
|
||||
enum lfs_open_flags {
|
||||
// open flags
|
||||
LFS_O_RDONLY = 1, // Open a file as read only
|
||||
#ifndef LFS_READONLY
|
||||
LFS_O_WRONLY = 2, // Open a file as write only
|
||||
LFS_O_RDWR = 3, // Open a file as read and write
|
||||
LFS_O_CREAT = 0x0100, // Create a file if it does not exist
|
||||
LFS_O_EXCL = 0x0200, // Fail if a file already exists
|
||||
LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size
|
||||
LFS_O_APPEND = 0x0800, // Move to end of file on every write
|
||||
#endif
|
||||
|
||||
// internally used flags
|
||||
#ifndef LFS_READONLY
|
||||
LFS_F_DIRTY = 0x010000, // File does not match storage
|
||||
LFS_F_WRITING = 0x020000, // File has been written since last flush
|
||||
#endif
|
||||
LFS_F_READING = 0x040000, // File has been read since last flush
|
||||
#ifndef LFS_READONLY
|
||||
LFS_F_ERRED = 0x080000, // An error occurred during write
|
||||
#endif
|
||||
LFS_F_INLINE = 0x100000, // Currently inlined in directory entry
|
||||
};
|
||||
|
||||
// File seek flags
|
||||
enum lfs_whence_flags {
|
||||
LFS_SEEK_SET = 0, // Seek relative to an absolute position
|
||||
LFS_SEEK_CUR = 1, // Seek relative to the current file position
|
||||
LFS_SEEK_END = 2, // Seek relative to the end of the file
|
||||
};
|
||||
|
||||
|
||||
// Configuration provided during initialization of the littlefs
|
||||
struct lfs_config {
|
||||
// Opaque user provided context that can be used to pass
|
||||
// information to the block device operations
|
||||
void *context;
|
||||
|
||||
// Read a region in a block. Negative error codes are propagated
|
||||
// to the user.
|
||||
int (*read)(const struct lfs_config *c, lfs_block_t block,
|
||||
lfs_off_t off, void *buffer, lfs_size_t size);
|
||||
|
||||
// Program a region in a block. The block must have previously
|
||||
// been erased. Negative error codes are propagated to the user.
|
||||
// May return LFS_ERR_CORRUPT if the block should be considered bad.
|
||||
int (*prog)(const struct lfs_config *c, lfs_block_t block,
|
||||
lfs_off_t off, const void *buffer, lfs_size_t size);
|
||||
|
||||
// Erase a block. A block must be erased before being programmed.
|
||||
// The state of an erased block is undefined. Negative error codes
|
||||
// are propagated to the user.
|
||||
// May return LFS_ERR_CORRUPT if the block should be considered bad.
|
||||
int (*erase)(const struct lfs_config *c, lfs_block_t block);
|
||||
|
||||
// Sync the state of the underlying block device. Negative error codes
|
||||
// are propagated to the user.
|
||||
int (*sync)(const struct lfs_config *c);
|
||||
|
||||
#ifdef LFS_THREADSAFE
|
||||
// Lock the underlying block device. Negative error codes
|
||||
// are propagated to the user.
|
||||
int (*lock)(const struct lfs_config *c);
|
||||
|
||||
// Unlock the underlying block device. Negative error codes
|
||||
// are propagated to the user.
|
||||
int (*unlock)(const struct lfs_config *c);
|
||||
#endif
|
||||
|
||||
// Minimum size of a block read in bytes. All read operations will be a
|
||||
// multiple of this value.
|
||||
lfs_size_t read_size;
|
||||
|
||||
// Minimum size of a block program in bytes. All program operations will be
|
||||
// a multiple of this value.
|
||||
lfs_size_t prog_size;
|
||||
|
||||
// Size of an erasable block in bytes. This does not impact ram consumption
|
||||
// and may be larger than the physical erase size. However, non-inlined
|
||||
// files take up at minimum one block. Must be a multiple of the read and
|
||||
// program sizes.
|
||||
lfs_size_t block_size;
|
||||
|
||||
// Number of erasable blocks on the device. Defaults to block_count stored
|
||||
// on disk when zero.
|
||||
lfs_size_t block_count;
|
||||
|
||||
// Number of erase cycles before littlefs evicts metadata logs and moves
|
||||
// the metadata to another block. Suggested values are in the
|
||||
// range 100-1000, with large values having better performance at the cost
|
||||
// of less consistent wear distribution.
|
||||
//
|
||||
// Set to -1 to disable block-level wear-leveling.
|
||||
int32_t block_cycles;
|
||||
|
||||
// Size of block caches in bytes. Each cache buffers a portion of a block in
|
||||
// RAM. The littlefs needs a read cache, a program cache, and one additional
|
||||
// cache per file. Larger caches can improve performance by storing more
|
||||
// data and reducing the number of disk accesses. Must be a multiple of the
|
||||
// read and program sizes, and a factor of the block size.
|
||||
lfs_size_t cache_size;
|
||||
|
||||
// Size of the lookahead buffer in bytes. A larger lookahead buffer
|
||||
// increases the number of blocks found during an allocation pass. The
|
||||
// lookahead buffer is stored as a compact bitmap, so each byte of RAM
|
||||
// can track 8 blocks.
|
||||
lfs_size_t lookahead_size;
|
||||
|
||||
// Threshold for metadata compaction during lfs_fs_gc in bytes. Metadata
|
||||
// pairs that exceed this threshold will be compacted during lfs_fs_gc.
|
||||
// Defaults to ~88% block_size when zero, though the default may change
|
||||
// in the future.
|
||||
//
|
||||
// Note this only affects lfs_fs_gc. Normal compactions still only occur
|
||||
// when full.
|
||||
//
|
||||
// Set to -1 to disable metadata compaction during lfs_fs_gc.
|
||||
lfs_size_t compact_thresh;
|
||||
|
||||
// Optional statically allocated read buffer. Must be cache_size.
|
||||
// By default lfs_malloc is used to allocate this buffer.
|
||||
void *read_buffer;
|
||||
|
||||
// Optional statically allocated program buffer. Must be cache_size.
|
||||
// By default lfs_malloc is used to allocate this buffer.
|
||||
void *prog_buffer;
|
||||
|
||||
// Optional statically allocated lookahead buffer. Must be lookahead_size.
|
||||
// By default lfs_malloc is used to allocate this buffer.
|
||||
void *lookahead_buffer;
|
||||
|
||||
// Optional upper limit on length of file names in bytes. No downside for
|
||||
// larger names except the size of the info struct which is controlled by
|
||||
// the LFS_NAME_MAX define. Defaults to LFS_NAME_MAX or name_max stored on
|
||||
// disk when zero.
|
||||
lfs_size_t name_max;
|
||||
|
||||
// Optional upper limit on files in bytes. No downside for larger files
|
||||
// but must be <= LFS_FILE_MAX. Defaults to LFS_FILE_MAX or file_max stored
|
||||
// on disk when zero.
|
||||
lfs_size_t file_max;
|
||||
|
||||
// Optional upper limit on custom attributes in bytes. No downside for
|
||||
// larger attributes size but must be <= LFS_ATTR_MAX. Defaults to
|
||||
// LFS_ATTR_MAX or attr_max stored on disk when zero.
|
||||
lfs_size_t attr_max;
|
||||
|
||||
// Optional upper limit on total space given to metadata pairs in bytes. On
|
||||
// devices with large blocks (e.g. 128kB) setting this to a low size (2-8kB)
|
||||
// can help bound the metadata compaction time. Must be <= block_size.
|
||||
// Defaults to block_size when zero.
|
||||
lfs_size_t metadata_max;
|
||||
|
||||
// Optional upper limit on inlined files in bytes. Inlined files live in
|
||||
// metadata and decrease storage requirements, but may be limited to
|
||||
// improve metadata-related performance. Must be <= cache_size, <=
|
||||
// attr_max, and <= block_size/8. Defaults to the largest possible
|
||||
// inline_max when zero.
|
||||
//
|
||||
// Set to -1 to disable inlined files.
|
||||
lfs_size_t inline_max;
|
||||
|
||||
#ifdef LFS_MULTIVERSION
|
||||
// On-disk version to use when writing in the form of 16-bit major version
|
||||
// + 16-bit minor version. This limiting metadata to what is supported by
|
||||
// older minor versions. Note that some features will be lost. Defaults to
|
||||
// to the most recent minor version when zero.
|
||||
uint32_t disk_version;
|
||||
#endif
|
||||
};
|
||||
|
||||
// File info structure
|
||||
struct lfs_info {
|
||||
// Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR
|
||||
uint8_t type;
|
||||
|
||||
// Size of the file, only valid for REG files. Limited to 32-bits.
|
||||
lfs_size_t size;
|
||||
|
||||
// Name of the file stored as a null-terminated string. Limited to
|
||||
// LFS_NAME_MAX+1, which can be changed by redefining LFS_NAME_MAX to
|
||||
// reduce RAM. LFS_NAME_MAX is stored in superblock and must be
|
||||
// respected by other littlefs drivers.
|
||||
char name[LFS_NAME_MAX+1];
|
||||
};
|
||||
|
||||
// Filesystem info structure
|
||||
struct lfs_fsinfo {
|
||||
// On-disk version.
|
||||
uint32_t disk_version;
|
||||
|
||||
// Size of a logical block in bytes.
|
||||
lfs_size_t block_size;
|
||||
|
||||
// Number of logical blocks in filesystem.
|
||||
lfs_size_t block_count;
|
||||
|
||||
// Upper limit on the length of file names in bytes.
|
||||
lfs_size_t name_max;
|
||||
|
||||
// Upper limit on the size of files in bytes.
|
||||
lfs_size_t file_max;
|
||||
|
||||
// Upper limit on the size of custom attributes in bytes.
|
||||
lfs_size_t attr_max;
|
||||
};
|
||||
|
||||
// Custom attribute structure, used to describe custom attributes
|
||||
// committed atomically during file writes.
|
||||
struct lfs_attr {
|
||||
// 8-bit type of attribute, provided by user and used to
|
||||
// identify the attribute
|
||||
uint8_t type;
|
||||
|
||||
// Pointer to buffer containing the attribute
|
||||
void *buffer;
|
||||
|
||||
// Size of attribute in bytes, limited to LFS_ATTR_MAX
|
||||
lfs_size_t size;
|
||||
};
|
||||
|
||||
// Optional configuration provided during lfs_file_opencfg
|
||||
struct lfs_file_config {
|
||||
// Optional statically allocated file buffer. Must be cache_size.
|
||||
// By default lfs_malloc is used to allocate this buffer.
|
||||
void *buffer;
|
||||
|
||||
// Optional list of custom attributes related to the file. If the file
|
||||
// is opened with read access, these attributes will be read from disk
|
||||
// during the open call. If the file is opened with write access, the
|
||||
// attributes will be written to disk every file sync or close. This
|
||||
// write occurs atomically with update to the file's contents.
|
||||
//
|
||||
// Custom attributes are uniquely identified by an 8-bit type and limited
|
||||
// to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller
|
||||
// than the buffer, it will be padded with zeros. If the stored attribute
|
||||
// is larger, then it will be silently truncated. If the attribute is not
|
||||
// found, it will be created implicitly.
|
||||
struct lfs_attr *attrs;
|
||||
|
||||
// Number of custom attributes in the list
|
||||
lfs_size_t attr_count;
|
||||
};
|
||||
|
||||
|
||||
/// internal littlefs data structures ///
|
||||
typedef struct lfs_cache {
|
||||
lfs_block_t block;
|
||||
lfs_off_t off;
|
||||
lfs_size_t size;
|
||||
uint8_t *buffer;
|
||||
} lfs_cache_t;
|
||||
|
||||
typedef struct lfs_mdir {
|
||||
lfs_block_t pair[2];
|
||||
uint32_t rev;
|
||||
lfs_off_t off;
|
||||
uint32_t etag;
|
||||
uint16_t count;
|
||||
bool erased;
|
||||
bool split;
|
||||
lfs_block_t tail[2];
|
||||
} lfs_mdir_t;
|
||||
|
||||
// littlefs directory type
|
||||
typedef struct lfs_dir {
|
||||
struct lfs_dir *next;
|
||||
uint16_t id;
|
||||
uint8_t type;
|
||||
lfs_mdir_t m;
|
||||
|
||||
lfs_off_t pos;
|
||||
lfs_block_t head[2];
|
||||
} lfs_dir_t;
|
||||
|
||||
// littlefs file type
|
||||
typedef struct lfs_file {
|
||||
struct lfs_file *next;
|
||||
uint16_t id;
|
||||
uint8_t type;
|
||||
lfs_mdir_t m;
|
||||
|
||||
struct lfs_ctz {
|
||||
lfs_block_t head;
|
||||
lfs_size_t size;
|
||||
} ctz;
|
||||
|
||||
uint32_t flags;
|
||||
lfs_off_t pos;
|
||||
lfs_block_t block;
|
||||
lfs_off_t off;
|
||||
lfs_cache_t cache;
|
||||
|
||||
const struct lfs_file_config *cfg;
|
||||
} lfs_file_t;
|
||||
|
||||
typedef struct lfs_superblock {
|
||||
uint32_t version;
|
||||
lfs_size_t block_size;
|
||||
lfs_size_t block_count;
|
||||
lfs_size_t name_max;
|
||||
lfs_size_t file_max;
|
||||
lfs_size_t attr_max;
|
||||
} lfs_superblock_t;
|
||||
|
||||
typedef struct lfs_gstate {
|
||||
uint32_t tag;
|
||||
lfs_block_t pair[2];
|
||||
} lfs_gstate_t;
|
||||
|
||||
// The littlefs filesystem type
|
||||
typedef struct lfs {
|
||||
lfs_cache_t rcache;
|
||||
lfs_cache_t pcache;
|
||||
|
||||
lfs_block_t root[2];
|
||||
struct lfs_mlist {
|
||||
struct lfs_mlist *next;
|
||||
uint16_t id;
|
||||
uint8_t type;
|
||||
lfs_mdir_t m;
|
||||
} *mlist;
|
||||
uint32_t seed;
|
||||
|
||||
lfs_gstate_t gstate;
|
||||
lfs_gstate_t gdisk;
|
||||
lfs_gstate_t gdelta;
|
||||
|
||||
struct lfs_lookahead {
|
||||
lfs_block_t start;
|
||||
lfs_block_t size;
|
||||
lfs_block_t next;
|
||||
lfs_block_t ckpoint;
|
||||
uint8_t *buffer;
|
||||
} lookahead;
|
||||
|
||||
const struct lfs_config *cfg;
|
||||
lfs_size_t block_count;
|
||||
lfs_size_t name_max;
|
||||
lfs_size_t file_max;
|
||||
lfs_size_t attr_max;
|
||||
lfs_size_t inline_max;
|
||||
|
||||
#ifdef LFS_MIGRATE
|
||||
struct lfs1 *lfs1;
|
||||
#endif
|
||||
} lfs_t;
|
||||
|
||||
|
||||
/// Filesystem functions ///
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
// Format a block device with the littlefs
|
||||
//
|
||||
// Requires a littlefs object and config struct. This clobbers the littlefs
|
||||
// object, and does not leave the filesystem mounted. The config struct must
|
||||
// be zeroed for defaults and backwards compatibility.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_format(lfs_t *lfs, const struct lfs_config *config);
|
||||
#endif
|
||||
|
||||
// Mounts a littlefs
|
||||
//
|
||||
// Requires a littlefs object and config struct. Multiple filesystems
|
||||
// may be mounted simultaneously with multiple littlefs objects. Both
|
||||
// lfs and config must be allocated while mounted. The config struct must
|
||||
// be zeroed for defaults and backwards compatibility.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_mount(lfs_t *lfs, const struct lfs_config *config);
|
||||
|
||||
// Unmounts a littlefs
|
||||
//
|
||||
// Does nothing besides releasing any allocated resources.
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_unmount(lfs_t *lfs);
|
||||
|
||||
/// General operations ///
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
// Removes a file or directory
|
||||
//
|
||||
// If removing a directory, the directory must be empty.
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_remove(lfs_t *lfs, const char *path);
|
||||
#endif
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
// Rename or move a file or directory
|
||||
//
|
||||
// If the destination exists, it must match the source in type.
|
||||
// If the destination is a directory, the directory must be empty.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath);
|
||||
#endif
|
||||
|
||||
// Find info about a file or directory
|
||||
//
|
||||
// Fills out the info structure, based on the specified file or directory.
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
|
||||
|
||||
// Get a custom attribute
|
||||
//
|
||||
// Custom attributes are uniquely identified by an 8-bit type and limited
|
||||
// to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller than
|
||||
// the buffer, it will be padded with zeros. If the stored attribute is larger,
|
||||
// then it will be silently truncated. If no attribute is found, the error
|
||||
// LFS_ERR_NOATTR is returned and the buffer is filled with zeros.
|
||||
//
|
||||
// Returns the size of the attribute, or a negative error code on failure.
|
||||
// Note, the returned size is the size of the attribute on disk, irrespective
|
||||
// of the size of the buffer. This can be used to dynamically allocate a buffer
|
||||
// or check for existence.
|
||||
lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
|
||||
uint8_t type, void *buffer, lfs_size_t size);
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
// Set custom attributes
|
||||
//
|
||||
// Custom attributes are uniquely identified by an 8-bit type and limited
|
||||
// to LFS_ATTR_MAX bytes. If an attribute is not found, it will be
|
||||
// implicitly created.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_setattr(lfs_t *lfs, const char *path,
|
||||
uint8_t type, const void *buffer, lfs_size_t size);
|
||||
#endif
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
// Removes a custom attribute
|
||||
//
|
||||
// If an attribute is not found, nothing happens.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type);
|
||||
#endif
|
||||
|
||||
|
||||
/// File operations ///
|
||||
|
||||
#ifndef LFS_NO_MALLOC
|
||||
// Open a file
|
||||
//
|
||||
// The mode that the file is opened in is determined by the flags, which
|
||||
// are values from the enum lfs_open_flags that are bitwise-ored together.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
|
||||
const char *path, int flags);
|
||||
|
||||
// if LFS_NO_MALLOC is defined, lfs_file_open() will fail with LFS_ERR_NOMEM
|
||||
// thus use lfs_file_opencfg() with config.buffer set.
|
||||
#endif
|
||||
|
||||
// Open a file with extra configuration
|
||||
//
|
||||
// The mode that the file is opened in is determined by the flags, which
|
||||
// are values from the enum lfs_open_flags that are bitwise-ored together.
|
||||
//
|
||||
// The config struct provides additional config options per file as described
|
||||
// above. The config struct must remain allocated while the file is open, and
|
||||
// the config struct must be zeroed for defaults and backwards compatibility.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
|
||||
const char *path, int flags,
|
||||
const struct lfs_file_config *config);
|
||||
|
||||
// Close a file
|
||||
//
|
||||
// Any pending writes are written out to storage as though
|
||||
// sync had been called and releases any allocated resources.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_file_close(lfs_t *lfs, lfs_file_t *file);
|
||||
|
||||
// Synchronize a file on storage
|
||||
//
|
||||
// Any pending writes are written out to storage.
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_file_sync(lfs_t *lfs, lfs_file_t *file);
|
||||
|
||||
// Read data from file
|
||||
//
|
||||
// Takes a buffer and size indicating where to store the read data.
|
||||
// Returns the number of bytes read, or a negative error code on failure.
|
||||
lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
|
||||
void *buffer, lfs_size_t size);
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
// Write data to file
|
||||
//
|
||||
// Takes a buffer and size indicating the data to write. The file will not
|
||||
// actually be updated on the storage until either sync or close is called.
|
||||
//
|
||||
// Returns the number of bytes written, or a negative error code on failure.
|
||||
lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
|
||||
const void *buffer, lfs_size_t size);
|
||||
#endif
|
||||
|
||||
// Change the position of the file
|
||||
//
|
||||
// The change in position is determined by the offset and whence flag.
|
||||
// Returns the new position of the file, or a negative error code on failure.
|
||||
lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
|
||||
lfs_soff_t off, int whence);
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
// Truncates the size of the file to the specified size
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size);
|
||||
#endif
|
||||
|
||||
// Return the position of the file
|
||||
//
|
||||
// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR)
|
||||
// Returns the position of the file, or a negative error code on failure.
|
||||
lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file);
|
||||
|
||||
// Change the position of the file to the beginning of the file
|
||||
//
|
||||
// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_SET)
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file);
|
||||
|
||||
// Return the size of the file
|
||||
//
|
||||
// Similar to lfs_file_seek(lfs, file, 0, LFS_SEEK_END)
|
||||
// Returns the size of the file, or a negative error code on failure.
|
||||
lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file);
|
||||
|
||||
|
||||
/// Directory operations ///
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
// Create a directory
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_mkdir(lfs_t *lfs, const char *path);
|
||||
#endif
|
||||
|
||||
// Open a directory
|
||||
//
|
||||
// Once open a directory can be used with read to iterate over files.
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path);
|
||||
|
||||
// Close a directory
|
||||
//
|
||||
// Releases any allocated resources.
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir);
|
||||
|
||||
// Read an entry in the directory
|
||||
//
|
||||
// Fills out the info structure, based on the specified file or directory.
|
||||
// Returns a positive value on success, 0 at the end of directory,
|
||||
// or a negative error code on failure.
|
||||
int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info);
|
||||
|
||||
// Change the position of the directory
|
||||
//
|
||||
// The new off must be a value previous returned from tell and specifies
|
||||
// an absolute offset in the directory seek.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off);
|
||||
|
||||
// Return the position of the directory
|
||||
//
|
||||
// The returned offset is only meant to be consumed by seek and may not make
|
||||
// sense, but does indicate the current position in the directory iteration.
|
||||
//
|
||||
// Returns the position of the directory, or a negative error code on failure.
|
||||
lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir);
|
||||
|
||||
// Change the position of the directory to the beginning of the directory
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir);
|
||||
|
||||
|
||||
/// Filesystem-level filesystem operations
|
||||
|
||||
// Find on-disk info about the filesystem
|
||||
//
|
||||
// Fills out the fsinfo structure based on the filesystem found on-disk.
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_fs_stat(lfs_t *lfs, struct lfs_fsinfo *fsinfo);
|
||||
|
||||
// Finds the current size of the filesystem
|
||||
//
|
||||
// Note: Result is best effort. If files share COW structures, the returned
|
||||
// size may be larger than the filesystem actually is.
|
||||
//
|
||||
// Returns the number of allocated blocks, or a negative error code on failure.
|
||||
lfs_ssize_t lfs_fs_size(lfs_t *lfs);
|
||||
|
||||
// Traverse through all blocks in use by the filesystem
|
||||
//
|
||||
// The provided callback will be called with each block address that is
|
||||
// currently in use by the filesystem. This can be used to determine which
|
||||
// blocks are in use or how much of the storage is available.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data);
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
// Attempt to make the filesystem consistent and ready for writing
|
||||
//
|
||||
// Calling this function is not required, consistency will be implicitly
|
||||
// enforced on the first operation that writes to the filesystem, but this
|
||||
// function allows the work to be performed earlier and without other
|
||||
// filesystem changes.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_fs_mkconsistent(lfs_t *lfs);
|
||||
#endif
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
// Attempt any janitorial work
|
||||
//
|
||||
// This currently:
|
||||
// 1. Calls mkconsistent if not already consistent
|
||||
// 2. Compacts metadata > compact_thresh
|
||||
// 3. Populates the block allocator
|
||||
//
|
||||
// Though additional janitorial work may be added in the future.
|
||||
//
|
||||
// Calling this function is not required, but may allow the offloading of
|
||||
// expensive janitorial work to a less time-critical code path.
|
||||
//
|
||||
// Returns a negative error code on failure. Accomplishing nothing is not
|
||||
// an error.
|
||||
int lfs_fs_gc(lfs_t *lfs);
|
||||
#endif
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
// Grows the filesystem to a new size, updating the superblock with the new
|
||||
// block count.
|
||||
//
|
||||
// If LFS_SHRINKNONRELOCATING is defined, this function will also accept
|
||||
// block_counts smaller than the current configuration, after checking
|
||||
// that none of the blocks that are being removed are in use.
|
||||
// Note that littlefs's pseudorandom block allocation means that
|
||||
// this is very unlikely to work in the general case.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_fs_grow(lfs_t *lfs, lfs_size_t block_count);
|
||||
#endif
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
#ifdef LFS_MIGRATE
|
||||
// Attempts to migrate a previous version of littlefs
|
||||
//
|
||||
// Behaves similarly to the lfs_format function. Attempts to mount
|
||||
// the previous version of littlefs and update the filesystem so it can be
|
||||
// mounted with the current version of littlefs.
|
||||
//
|
||||
// Requires a littlefs object and config struct. This clobbers the littlefs
|
||||
// object, and does not leave the filesystem mounted. The config struct must
|
||||
// be zeroed for defaults and backwards compatibility.
|
||||
//
|
||||
// Returns a negative error code on failure.
|
||||
int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
#ifndef _LFS_CONFIG_H_
|
||||
#define _LFS_CONFIG_H_
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
// System includes
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
// Macros, may be replaced by system specific wrappers. Arguments to these
|
||||
// macros must not have side-effects as the macros can be removed for a smaller
|
||||
// code footprint
|
||||
|
||||
// Logging functions
|
||||
#ifdef LFS_YES_TRACE
|
||||
#define LFS_TRACE(fmt, ...) \
|
||||
rt_kprintf("%s:%d:trace: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
|
||||
#define LFS_TRACE(...) LFS_TRACE_(__VA_ARGS__, "")
|
||||
#else
|
||||
#define LFS_TRACE(...)
|
||||
#endif
|
||||
|
||||
#ifndef LFS_NO_DEBUG
|
||||
#define LFS_DEBUG_(fmt, ...) \
|
||||
rt_kprintf("%s:%d:debug: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
|
||||
#define LFS_DEBUG(...) LFS_DEBUG_(__VA_ARGS__, "")
|
||||
#else
|
||||
#define LFS_DEBUG(...)
|
||||
#endif
|
||||
|
||||
#ifndef LFS_NO_WARN
|
||||
#define LFS_WARN_(fmt, ...) \
|
||||
rt_kprintf("%s:%d:warn: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
|
||||
#define LFS_WARN(...) LFS_WARN_(__VA_ARGS__, "")
|
||||
#else
|
||||
#define LFS_WARN(...)
|
||||
#endif
|
||||
|
||||
#ifndef LFS_NO_ERROR
|
||||
#define LFS_ERROR_(fmt, ...) \
|
||||
rt_kprintf("%s:%d:error: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
|
||||
#define LFS_ERROR(...) LFS_ERROR_(__VA_ARGS__, "")
|
||||
#else
|
||||
#define LFS_ERROR(...)
|
||||
#endif
|
||||
|
||||
// Runtime assertions
|
||||
#ifndef LFS_NO_ASSERT
|
||||
#define LFS_ASSERT(test) RT_ASSERT(test)
|
||||
#else
|
||||
#define LFS_ASSERT(test)
|
||||
#endif
|
||||
|
||||
|
||||
// Builtin functions, these may be replaced by more efficient
|
||||
// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
|
||||
// expensive basic C implementation for debugging purposes
|
||||
|
||||
// Min/max functions for unsigned 32-bit numbers
|
||||
static inline uint32_t lfs_max(uint32_t a, uint32_t b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
static inline uint32_t lfs_min(uint32_t a, uint32_t b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
// Align to nearest multiple of a size
|
||||
static inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) {
|
||||
return a - (a % alignment);
|
||||
}
|
||||
|
||||
static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) {
|
||||
return lfs_aligndown(a + alignment-1, alignment);
|
||||
}
|
||||
|
||||
// Find the smallest power of 2 greater than or equal to a
|
||||
static inline uint32_t lfs_npw2(uint32_t a) {
|
||||
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
|
||||
return 32 - __builtin_clz(a-1);
|
||||
#else
|
||||
uint32_t r = 0;
|
||||
uint32_t s;
|
||||
a -= 1;
|
||||
s = (a > 0xffff) << 4; a >>= s; r |= s;
|
||||
s = (a > 0xff ) << 3; a >>= s; r |= s;
|
||||
s = (a > 0xf ) << 2; a >>= s; r |= s;
|
||||
s = (a > 0x3 ) << 1; a >>= s; r |= s;
|
||||
return (r | (a >> 1)) + 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Count the number of trailing binary zeros in a
|
||||
// lfs_ctz(0) may be undefined
|
||||
static inline uint32_t lfs_ctz(uint32_t a) {
|
||||
#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)
|
||||
return __builtin_ctz(a);
|
||||
#else
|
||||
return lfs_npw2((a & -a) + 1) - 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Count the number of binary ones in a
|
||||
static inline uint32_t lfs_popc(uint32_t a) {
|
||||
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
|
||||
return __builtin_popcount(a);
|
||||
#else
|
||||
a = a - ((a >> 1) & 0x55555555);
|
||||
a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
|
||||
return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Find the sequence comparison of a and b, this is the distance
|
||||
// between a and b ignoring overflow
|
||||
static inline int lfs_scmp(uint32_t a, uint32_t b) {
|
||||
return (int)(unsigned)(a - b);
|
||||
}
|
||||
|
||||
// Convert between 32-bit little-endian and native order
|
||||
static inline uint32_t lfs_fromle32(uint32_t a) {
|
||||
#if !defined(LFS_NO_INTRINSICS) && ( \
|
||||
(defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
||||
return a;
|
||||
#elif !defined(LFS_NO_INTRINSICS) && ( \
|
||||
(defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||
return __builtin_bswap32(a);
|
||||
#else
|
||||
return (((uint8_t*)&a)[0] << 0) |
|
||||
(((uint8_t*)&a)[1] << 8) |
|
||||
(((uint8_t*)&a)[2] << 16) |
|
||||
(((uint8_t*)&a)[3] << 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint32_t lfs_tole32(uint32_t a) {
|
||||
return lfs_fromle32(a);
|
||||
}
|
||||
|
||||
// Convert between 32-bit big-endian and native order
|
||||
static inline uint32_t lfs_frombe32(uint32_t a) {
|
||||
#if !defined(LFS_NO_INTRINSICS) && ( \
|
||||
(defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
||||
return __builtin_bswap32(a);
|
||||
#elif !defined(LFS_NO_INTRINSICS) && ( \
|
||||
(defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||
return a;
|
||||
#else
|
||||
return (((uint8_t*)&a)[0] << 24) |
|
||||
(((uint8_t*)&a)[1] << 16) |
|
||||
(((uint8_t*)&a)[2] << 8) |
|
||||
(((uint8_t*)&a)[3] << 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint32_t lfs_tobe32(uint32_t a) {
|
||||
return lfs_frombe32(a);
|
||||
}
|
||||
|
||||
// Calculate CRC-32 with polynomial = 0x04c11db7
|
||||
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size);
|
||||
|
||||
// Allocate memory, only used if buffers are not provided to littlefs
|
||||
// Note, memory must be 64-bit aligned
|
||||
static inline void *lfs_malloc(size_t size) {
|
||||
#ifndef LFS_NO_MALLOC
|
||||
return rt_malloc(size);
|
||||
#else
|
||||
(void)size;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Deallocate memory, only used if buffers are not provided to littlefs
|
||||
static inline void lfs_free(void *p) {
|
||||
#ifndef LFS_NO_MALLOC
|
||||
rt_free(p);
|
||||
#else
|
||||
(void)p;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
#include "lfs_util.h"
|
||||
|
||||
// Software CRC implementation with small lookup table
|
||||
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {
|
||||
static const uint32_t rtable[16] = {
|
||||
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
|
||||
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
|
||||
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
|
||||
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
|
||||
};
|
||||
|
||||
const uint8_t *data = buffer;
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 0)) & 0xf];
|
||||
crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 4)) & 0xf];
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
Vendored
+37
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* lfs util functions
|
||||
*
|
||||
* Copyright (c) 2022, The littlefs authors.
|
||||
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include "lfs_util.h"
|
||||
|
||||
// Only compile if user does not provide custom config
|
||||
#ifndef LFS_CONFIG
|
||||
|
||||
|
||||
// If user provides their own CRC impl we don't need this
|
||||
#ifndef LFS_CRC
|
||||
// Software CRC implementation with small lookup table
|
||||
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {
|
||||
static const uint32_t rtable[16] = {
|
||||
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
|
||||
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
|
||||
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
|
||||
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
|
||||
};
|
||||
|
||||
const uint8_t *data = buffer;
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 0)) & 0xf];
|
||||
crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 4)) & 0xf];
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
Vendored
+273
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* lfs utility functions
|
||||
*
|
||||
* Copyright (c) 2022, The littlefs authors.
|
||||
* Copyright (c) 2017, Arm Limited. All rights reserved.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef LFS_UTIL_H
|
||||
#define LFS_UTIL_H
|
||||
|
||||
#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
|
||||
#define LFS_STRINGIZE2(x) #x
|
||||
|
||||
// Users can override lfs_util.h with their own configuration by defining
|
||||
// LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h).
|
||||
//
|
||||
// If LFS_CONFIG is used, none of the default utils will be emitted and must be
|
||||
// provided by the config file. To start, I would suggest copying lfs_util.h
|
||||
// and modifying as needed.
|
||||
#ifdef LFS_CONFIG
|
||||
#include LFS_STRINGIZE(LFS_CONFIG)
|
||||
#else
|
||||
|
||||
// Alternatively, users can provide a header file which defines
|
||||
// macros and other things consumed by littlefs.
|
||||
//
|
||||
// For example, provide my_defines.h, which contains
|
||||
// something like:
|
||||
//
|
||||
// #include <stddef.h>
|
||||
// extern void *my_malloc(size_t sz);
|
||||
// #define LFS_MALLOC(sz) my_malloc(sz)
|
||||
//
|
||||
// And build littlefs with the header by defining LFS_DEFINES.
|
||||
// (-DLFS_DEFINES=my_defines.h)
|
||||
|
||||
#ifdef LFS_DEFINES
|
||||
#include LFS_STRINGIZE(LFS_DEFINES)
|
||||
#endif
|
||||
|
||||
// System includes
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifndef LFS_NO_MALLOC
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
#ifndef LFS_NO_ASSERT
|
||||
#include <assert.h>
|
||||
#endif
|
||||
#if !defined(LFS_NO_DEBUG) || \
|
||||
!defined(LFS_NO_WARN) || \
|
||||
!defined(LFS_NO_ERROR) || \
|
||||
defined(LFS_YES_TRACE)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
// Macros, may be replaced by system specific wrappers. Arguments to these
|
||||
// macros must not have side-effects as the macros can be removed for a smaller
|
||||
// code footprint
|
||||
|
||||
// Logging functions
|
||||
#ifndef LFS_TRACE
|
||||
#ifdef LFS_YES_TRACE
|
||||
#define LFS_TRACE_(fmt, ...) \
|
||||
printf("%s:%d:trace: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
|
||||
#define LFS_TRACE(...) LFS_TRACE_(__VA_ARGS__, "")
|
||||
#else
|
||||
#define LFS_TRACE(...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef LFS_DEBUG
|
||||
#ifndef LFS_NO_DEBUG
|
||||
#define LFS_DEBUG_(fmt, ...) \
|
||||
printf("%s:%d:debug: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
|
||||
#define LFS_DEBUG(...) LFS_DEBUG_(__VA_ARGS__, "")
|
||||
#else
|
||||
#define LFS_DEBUG(...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef LFS_WARN
|
||||
#ifndef LFS_NO_WARN
|
||||
#define LFS_WARN_(fmt, ...) \
|
||||
printf("%s:%d:warn: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
|
||||
#define LFS_WARN(...) LFS_WARN_(__VA_ARGS__, "")
|
||||
#else
|
||||
#define LFS_WARN(...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef LFS_ERROR
|
||||
#ifndef LFS_NO_ERROR
|
||||
#define LFS_ERROR_(fmt, ...) \
|
||||
printf("%s:%d:error: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
|
||||
#define LFS_ERROR(...) LFS_ERROR_(__VA_ARGS__, "")
|
||||
#else
|
||||
#define LFS_ERROR(...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Runtime assertions
|
||||
#ifndef LFS_ASSERT
|
||||
#ifndef LFS_NO_ASSERT
|
||||
#define LFS_ASSERT(test) assert(test)
|
||||
#else
|
||||
#define LFS_ASSERT(test)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// Builtin functions, these may be replaced by more efficient
|
||||
// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
|
||||
// expensive basic C implementation for debugging purposes
|
||||
|
||||
// Min/max functions for unsigned 32-bit numbers
|
||||
static inline uint32_t lfs_max(uint32_t a, uint32_t b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
static inline uint32_t lfs_min(uint32_t a, uint32_t b) {
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
// Align to nearest multiple of a size
|
||||
static inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) {
|
||||
return a - (a % alignment);
|
||||
}
|
||||
|
||||
static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) {
|
||||
return lfs_aligndown(a + alignment-1, alignment);
|
||||
}
|
||||
|
||||
// Find the smallest power of 2 greater than or equal to a
|
||||
static inline uint32_t lfs_npw2(uint32_t a) {
|
||||
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
|
||||
return 32 - __builtin_clz(a-1);
|
||||
#else
|
||||
uint32_t r = 0;
|
||||
uint32_t s;
|
||||
a -= 1;
|
||||
s = (a > 0xffff) << 4; a >>= s; r |= s;
|
||||
s = (a > 0xff ) << 3; a >>= s; r |= s;
|
||||
s = (a > 0xf ) << 2; a >>= s; r |= s;
|
||||
s = (a > 0x3 ) << 1; a >>= s; r |= s;
|
||||
return (r | (a >> 1)) + 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Count the number of trailing binary zeros in a
|
||||
// lfs_ctz(0) may be undefined
|
||||
static inline uint32_t lfs_ctz(uint32_t a) {
|
||||
#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)
|
||||
return __builtin_ctz(a);
|
||||
#else
|
||||
return lfs_npw2((a & -a) + 1) - 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Count the number of binary ones in a
|
||||
static inline uint32_t lfs_popc(uint32_t a) {
|
||||
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
|
||||
return __builtin_popcount(a);
|
||||
#else
|
||||
a = a - ((a >> 1) & 0x55555555);
|
||||
a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
|
||||
return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Find the sequence comparison of a and b, this is the distance
|
||||
// between a and b ignoring overflow
|
||||
static inline int lfs_scmp(uint32_t a, uint32_t b) {
|
||||
return (int)(unsigned)(a - b);
|
||||
}
|
||||
|
||||
// Convert between 32-bit little-endian and native order
|
||||
static inline uint32_t lfs_fromle32(uint32_t a) {
|
||||
#if (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
return a;
|
||||
#elif !defined(LFS_NO_INTRINSICS) && ( \
|
||||
(defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||
return __builtin_bswap32(a);
|
||||
#else
|
||||
return ((uint32_t)((uint8_t*)&a)[0] << 0) |
|
||||
((uint32_t)((uint8_t*)&a)[1] << 8) |
|
||||
((uint32_t)((uint8_t*)&a)[2] << 16) |
|
||||
((uint32_t)((uint8_t*)&a)[3] << 24);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint32_t lfs_tole32(uint32_t a) {
|
||||
return lfs_fromle32(a);
|
||||
}
|
||||
|
||||
// Convert between 32-bit big-endian and native order
|
||||
static inline uint32_t lfs_frombe32(uint32_t a) {
|
||||
#if !defined(LFS_NO_INTRINSICS) && ( \
|
||||
(defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
|
||||
return __builtin_bswap32(a);
|
||||
#elif (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
|
||||
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
return a;
|
||||
#else
|
||||
return ((uint32_t)((uint8_t*)&a)[0] << 24) |
|
||||
((uint32_t)((uint8_t*)&a)[1] << 16) |
|
||||
((uint32_t)((uint8_t*)&a)[2] << 8) |
|
||||
((uint32_t)((uint8_t*)&a)[3] << 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint32_t lfs_tobe32(uint32_t a) {
|
||||
return lfs_frombe32(a);
|
||||
}
|
||||
|
||||
// Calculate CRC-32 with polynomial = 0x04c11db7
|
||||
#ifdef LFS_CRC
|
||||
static inline uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {
|
||||
return LFS_CRC(crc, buffer, size);
|
||||
}
|
||||
#else
|
||||
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size);
|
||||
#endif
|
||||
|
||||
// Allocate memory, only used if buffers are not provided to littlefs
|
||||
//
|
||||
// littlefs current has no alignment requirements, as it only allocates
|
||||
// byte-level buffers.
|
||||
static inline void *lfs_malloc(size_t size) {
|
||||
#if defined(LFS_MALLOC)
|
||||
return LFS_MALLOC(size);
|
||||
#elif !defined(LFS_NO_MALLOC)
|
||||
return malloc(size);
|
||||
#else
|
||||
(void)size;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Deallocate memory, only used if buffers are not provided to littlefs
|
||||
static inline void lfs_free(void *p) {
|
||||
#if defined(LFS_FREE)
|
||||
LFS_FREE(p);
|
||||
#elif !defined(LFS_NO_MALLOC)
|
||||
free(p);
|
||||
#else
|
||||
(void)p;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
+2063
File diff suppressed because it is too large.
Load diff
+146
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Runner for littlefs benchmarks
|
||||
*
|
||||
* Copyright (c) 2022, The littlefs authors.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef BENCH_RUNNER_H
|
||||
#define BENCH_RUNNER_H
|
||||
|
||||
|
||||
// override LFS_TRACE
|
||||
void bench_trace(const char *fmt, ...);
|
||||
|
||||
#define LFS_TRACE_(fmt, ...) \
|
||||
bench_trace("%s:%d:trace: " fmt "%s\n", \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
__VA_ARGS__)
|
||||
#define LFS_TRACE(...) LFS_TRACE_(__VA_ARGS__, "")
|
||||
#define LFS_EMUBD_TRACE(...) LFS_TRACE_(__VA_ARGS__, "")
|
||||
|
||||
// provide BENCH_START/BENCH_STOP macros
|
||||
void bench_start(void);
|
||||
void bench_stop(void);
|
||||
|
||||
#define BENCH_START() bench_start()
|
||||
#define BENCH_STOP() bench_stop()
|
||||
|
||||
|
||||
// note these are indirectly included in any generated files
|
||||
#include "bd/lfs_emubd.h"
|
||||
#include <stdio.h>
|
||||
|
||||
// give source a chance to define feature macros
|
||||
#undef _FEATURES_H
|
||||
#undef _STDIO_H
|
||||
|
||||
|
||||
// generated bench configurations
|
||||
struct lfs_config;
|
||||
|
||||
enum bench_flags {
|
||||
BENCH_REENTRANT = 0x1,
|
||||
};
|
||||
typedef uint8_t bench_flags_t;
|
||||
|
||||
typedef struct bench_define {
|
||||
intmax_t (*cb)(void *data);
|
||||
void *data;
|
||||
} bench_define_t;
|
||||
|
||||
struct bench_case {
|
||||
const char *name;
|
||||
const char *path;
|
||||
bench_flags_t flags;
|
||||
size_t permutations;
|
||||
|
||||
const bench_define_t *defines;
|
||||
|
||||
bool (*filter)(void);
|
||||
void (*run)(struct lfs_config *cfg);
|
||||
};
|
||||
|
||||
struct bench_suite {
|
||||
const char *name;
|
||||
const char *path;
|
||||
bench_flags_t flags;
|
||||
|
||||
const char *const *define_names;
|
||||
size_t define_count;
|
||||
|
||||
const struct bench_case *cases;
|
||||
size_t case_count;
|
||||
};
|
||||
|
||||
|
||||
// deterministic prng for pseudo-randomness in benches
|
||||
uint32_t bench_prng(uint32_t *state);
|
||||
|
||||
#define BENCH_PRNG(state) bench_prng(state)
|
||||
|
||||
|
||||
// access generated bench defines
|
||||
intmax_t bench_define(size_t define);
|
||||
|
||||
#define BENCH_DEFINE(i) bench_define(i)
|
||||
|
||||
// a few preconfigured defines that control how benches run
|
||||
|
||||
#define READ_SIZE_i 0
|
||||
#define PROG_SIZE_i 1
|
||||
#define ERASE_SIZE_i 2
|
||||
#define ERASE_COUNT_i 3
|
||||
#define BLOCK_SIZE_i 4
|
||||
#define BLOCK_COUNT_i 5
|
||||
#define CACHE_SIZE_i 6
|
||||
#define LOOKAHEAD_SIZE_i 7
|
||||
#define COMPACT_THRESH_i 8
|
||||
#define METADATA_MAX_i 9
|
||||
#define INLINE_MAX_i 10
|
||||
#define BLOCK_CYCLES_i 11
|
||||
#define ERASE_VALUE_i 12
|
||||
#define ERASE_CYCLES_i 13
|
||||
#define BADBLOCK_BEHAVIOR_i 14
|
||||
#define POWERLOSS_BEHAVIOR_i 15
|
||||
|
||||
#define READ_SIZE bench_define(READ_SIZE_i)
|
||||
#define PROG_SIZE bench_define(PROG_SIZE_i)
|
||||
#define ERASE_SIZE bench_define(ERASE_SIZE_i)
|
||||
#define ERASE_COUNT bench_define(ERASE_COUNT_i)
|
||||
#define BLOCK_SIZE bench_define(BLOCK_SIZE_i)
|
||||
#define BLOCK_COUNT bench_define(BLOCK_COUNT_i)
|
||||
#define CACHE_SIZE bench_define(CACHE_SIZE_i)
|
||||
#define LOOKAHEAD_SIZE bench_define(LOOKAHEAD_SIZE_i)
|
||||
#define COMPACT_THRESH bench_define(COMPACT_THRESH_i)
|
||||
#define METADATA_MAX bench_define(METADATA_MAX_i)
|
||||
#define INLINE_MAX bench_define(INLINE_MAX_i)
|
||||
#define BLOCK_CYCLES bench_define(BLOCK_CYCLES_i)
|
||||
#define ERASE_VALUE bench_define(ERASE_VALUE_i)
|
||||
#define ERASE_CYCLES bench_define(ERASE_CYCLES_i)
|
||||
#define BADBLOCK_BEHAVIOR bench_define(BADBLOCK_BEHAVIOR_i)
|
||||
#define POWERLOSS_BEHAVIOR bench_define(POWERLOSS_BEHAVIOR_i)
|
||||
|
||||
#define BENCH_IMPLICIT_DEFINES \
|
||||
BENCH_DEF(READ_SIZE, PROG_SIZE) \
|
||||
BENCH_DEF(PROG_SIZE, ERASE_SIZE) \
|
||||
BENCH_DEF(ERASE_SIZE, 0) \
|
||||
BENCH_DEF(ERASE_COUNT, (1024*1024)/BLOCK_SIZE) \
|
||||
BENCH_DEF(BLOCK_SIZE, ERASE_SIZE) \
|
||||
BENCH_DEF(BLOCK_COUNT, ERASE_COUNT/lfs_max(BLOCK_SIZE/ERASE_SIZE,1))\
|
||||
BENCH_DEF(CACHE_SIZE, lfs_max(64,lfs_max(READ_SIZE,PROG_SIZE))) \
|
||||
BENCH_DEF(LOOKAHEAD_SIZE, 16) \
|
||||
BENCH_DEF(COMPACT_THRESH, 0) \
|
||||
BENCH_DEF(METADATA_MAX, 0) \
|
||||
BENCH_DEF(INLINE_MAX, 0) \
|
||||
BENCH_DEF(BLOCK_CYCLES, -1) \
|
||||
BENCH_DEF(ERASE_VALUE, 0xff) \
|
||||
BENCH_DEF(ERASE_CYCLES, 0) \
|
||||
BENCH_DEF(BADBLOCK_BEHAVIOR, LFS_EMUBD_BADBLOCK_PROGERROR) \
|
||||
BENCH_DEF(POWERLOSS_BEHAVIOR, LFS_EMUBD_POWERLOSS_NOOP)
|
||||
|
||||
#define BENCH_GEOMETRY_DEFINE_COUNT 4
|
||||
#define BENCH_IMPLICIT_DEFINE_COUNT 16
|
||||
|
||||
|
||||
#endif
|
||||
+2818
File diff suppressed because it is too large.
Load diff
+142
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Runner for littlefs tests
|
||||
*
|
||||
* Copyright (c) 2022, The littlefs authors.
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef TEST_RUNNER_H
|
||||
#define TEST_RUNNER_H
|
||||
|
||||
|
||||
// override LFS_TRACE
|
||||
void test_trace(const char *fmt, ...);
|
||||
|
||||
#define LFS_TRACE_(fmt, ...) \
|
||||
test_trace("%s:%d:trace: " fmt "%s\n", \
|
||||
__FILE__, \
|
||||
__LINE__, \
|
||||
__VA_ARGS__)
|
||||
#define LFS_TRACE(...) LFS_TRACE_(__VA_ARGS__, "")
|
||||
#define LFS_EMUBD_TRACE(...) LFS_TRACE_(__VA_ARGS__, "")
|
||||
|
||||
|
||||
// note these are indirectly included in any generated files
|
||||
#include "bd/lfs_emubd.h"
|
||||
#include <stdio.h>
|
||||
|
||||
// give source a chance to define feature macros
|
||||
#undef _FEATURES_H
|
||||
#undef _STDIO_H
|
||||
|
||||
|
||||
// generated test configurations
|
||||
struct lfs_config;
|
||||
|
||||
enum test_flags {
|
||||
TEST_REENTRANT = 0x1,
|
||||
};
|
||||
typedef uint8_t test_flags_t;
|
||||
|
||||
typedef struct test_define {
|
||||
intmax_t (*cb)(void *data);
|
||||
void *data;
|
||||
} test_define_t;
|
||||
|
||||
struct test_case {
|
||||
const char *name;
|
||||
const char *path;
|
||||
test_flags_t flags;
|
||||
size_t permutations;
|
||||
|
||||
const test_define_t *defines;
|
||||
|
||||
bool (*filter)(void);
|
||||
void (*run)(struct lfs_config *cfg);
|
||||
};
|
||||
|
||||
struct test_suite {
|
||||
const char *name;
|
||||
const char *path;
|
||||
test_flags_t flags;
|
||||
|
||||
const char *const *define_names;
|
||||
size_t define_count;
|
||||
|
||||
const struct test_case *cases;
|
||||
size_t case_count;
|
||||
};
|
||||
|
||||
|
||||
// deterministic prng for pseudo-randomness in testes
|
||||
uint32_t test_prng(uint32_t *state);
|
||||
|
||||
#define TEST_PRNG(state) test_prng(state)
|
||||
|
||||
|
||||
// access generated test defines
|
||||
intmax_t test_define(size_t define);
|
||||
|
||||
#define TEST_DEFINE(i) test_define(i)
|
||||
|
||||
// a few preconfigured defines that control how tests run
|
||||
|
||||
#define READ_SIZE_i 0
|
||||
#define PROG_SIZE_i 1
|
||||
#define ERASE_SIZE_i 2
|
||||
#define ERASE_COUNT_i 3
|
||||
#define BLOCK_SIZE_i 4
|
||||
#define BLOCK_COUNT_i 5
|
||||
#define CACHE_SIZE_i 6
|
||||
#define LOOKAHEAD_SIZE_i 7
|
||||
#define COMPACT_THRESH_i 8
|
||||
#define METADATA_MAX_i 9
|
||||
#define INLINE_MAX_i 10
|
||||
#define BLOCK_CYCLES_i 11
|
||||
#define ERASE_VALUE_i 12
|
||||
#define ERASE_CYCLES_i 13
|
||||
#define BADBLOCK_BEHAVIOR_i 14
|
||||
#define POWERLOSS_BEHAVIOR_i 15
|
||||
#define DISK_VERSION_i 16
|
||||
|
||||
#define READ_SIZE TEST_DEFINE(READ_SIZE_i)
|
||||
#define PROG_SIZE TEST_DEFINE(PROG_SIZE_i)
|
||||
#define ERASE_SIZE TEST_DEFINE(ERASE_SIZE_i)
|
||||
#define ERASE_COUNT TEST_DEFINE(ERASE_COUNT_i)
|
||||
#define BLOCK_SIZE TEST_DEFINE(BLOCK_SIZE_i)
|
||||
#define BLOCK_COUNT TEST_DEFINE(BLOCK_COUNT_i)
|
||||
#define CACHE_SIZE TEST_DEFINE(CACHE_SIZE_i)
|
||||
#define LOOKAHEAD_SIZE TEST_DEFINE(LOOKAHEAD_SIZE_i)
|
||||
#define COMPACT_THRESH TEST_DEFINE(COMPACT_THRESH_i)
|
||||
#define METADATA_MAX TEST_DEFINE(METADATA_MAX_i)
|
||||
#define INLINE_MAX TEST_DEFINE(INLINE_MAX_i)
|
||||
#define BLOCK_CYCLES TEST_DEFINE(BLOCK_CYCLES_i)
|
||||
#define ERASE_VALUE TEST_DEFINE(ERASE_VALUE_i)
|
||||
#define ERASE_CYCLES TEST_DEFINE(ERASE_CYCLES_i)
|
||||
#define BADBLOCK_BEHAVIOR TEST_DEFINE(BADBLOCK_BEHAVIOR_i)
|
||||
#define POWERLOSS_BEHAVIOR TEST_DEFINE(POWERLOSS_BEHAVIOR_i)
|
||||
#define DISK_VERSION TEST_DEFINE(DISK_VERSION_i)
|
||||
|
||||
#define TEST_IMPLICIT_DEFINES \
|
||||
TEST_DEF(READ_SIZE, PROG_SIZE) \
|
||||
TEST_DEF(PROG_SIZE, ERASE_SIZE) \
|
||||
TEST_DEF(ERASE_SIZE, 0) \
|
||||
TEST_DEF(ERASE_COUNT, (1024*1024)/ERASE_SIZE) \
|
||||
TEST_DEF(BLOCK_SIZE, ERASE_SIZE) \
|
||||
TEST_DEF(BLOCK_COUNT, ERASE_COUNT/lfs_max(BLOCK_SIZE/ERASE_SIZE,1)) \
|
||||
TEST_DEF(CACHE_SIZE, lfs_max(64,lfs_max(READ_SIZE,PROG_SIZE))) \
|
||||
TEST_DEF(LOOKAHEAD_SIZE, 16) \
|
||||
TEST_DEF(COMPACT_THRESH, 0) \
|
||||
TEST_DEF(METADATA_MAX, 0) \
|
||||
TEST_DEF(INLINE_MAX, 0) \
|
||||
TEST_DEF(BLOCK_CYCLES, -1) \
|
||||
TEST_DEF(ERASE_VALUE, 0xff) \
|
||||
TEST_DEF(ERASE_CYCLES, 0) \
|
||||
TEST_DEF(BADBLOCK_BEHAVIOR, LFS_EMUBD_BADBLOCK_PROGERROR) \
|
||||
TEST_DEF(POWERLOSS_BEHAVIOR, LFS_EMUBD_POWERLOSS_NOOP) \
|
||||
TEST_DEF(DISK_VERSION, 0)
|
||||
|
||||
#define TEST_GEOMETRY_DEFINE_COUNT 4
|
||||
#define TEST_IMPLICIT_DEFINE_COUNT 17
|
||||
|
||||
|
||||
#endif
|
||||
Binary file not shown.
@@ -8,5 +8,10 @@
|
||||
"path": "/packages/system/sqlite",
|
||||
"ver": "v3.19.3",
|
||||
"name": "SQLITE"
|
||||
},
|
||||
{
|
||||
"path": "/packages/system/littlefs",
|
||||
"ver": "v2.11.2",
|
||||
"name": "LITTLEFS"
|
||||
}
|
||||
]
|
||||
@@ -40,12 +40,12 @@ __exit:
|
||||
if ((result > 0) && (!init_ok))
|
||||
{
|
||||
init_ok = 1;
|
||||
log_i("RT-Thread Flash Abstraction Layer initialize success.");
|
||||
log_i("Flash Abstraction Layer initialize success.");
|
||||
}
|
||||
else if(result <= 0)
|
||||
{
|
||||
init_ok = 0;
|
||||
log_e("RT-Thread Flash Abstraction Layer initialize failed.");
|
||||
log_e("Flash Abstraction Layer initialize failed.");
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
+22
-1
@@ -88,7 +88,7 @@
|
||||
#define DFS_USING_WORKDIR
|
||||
#define DFS_FD_MAX 16
|
||||
#define RT_USING_DFS_V1
|
||||
#define DFS_FILESYSTEMS_MAX 4
|
||||
#define DFS_FILESYSTEMS_MAX 6
|
||||
#define DFS_FILESYSTEM_TYPES_MAX 4
|
||||
#define RT_USING_DFS_ELMFAT
|
||||
|
||||
@@ -111,6 +111,11 @@
|
||||
#define RT_USING_DFS_DEVFS
|
||||
#define RT_USING_DFS_TMPFS
|
||||
/* end of DFS: device virtual file system */
|
||||
#define RT_USING_FAL
|
||||
#define FAL_DEBUG 0
|
||||
#define FAL_PART_HAS_TABLE_CFG
|
||||
#define FAL_USING_SFUD_PORT
|
||||
#define FAL_USING_NOR_FLASH_DEV_NAME "W25Q128"
|
||||
|
||||
/* Device Drivers */
|
||||
|
||||
@@ -119,6 +124,7 @@
|
||||
#define RT_USING_SERIAL
|
||||
#define RT_USING_SERIAL_V1
|
||||
#define RT_SERIAL_RB_BUFSZ 512
|
||||
#define RT_USING_MTD_NOR
|
||||
#define RT_USING_RTC
|
||||
#define RT_USING_SOFT_RTC
|
||||
#define RT_USING_SDIO
|
||||
@@ -130,6 +136,11 @@
|
||||
#define RT_USING_SPI
|
||||
#define RT_USING_QSPI
|
||||
#define RT_USING_SPI_MSD
|
||||
#define RT_USING_SFUD
|
||||
#define RT_SFUD_USING_SFDP
|
||||
#define RT_SFUD_USING_FLASH_INFO_TABLE
|
||||
#define RT_SFUD_USING_QSPI
|
||||
#define RT_SFUD_SPI_MAX_HZ 50000000
|
||||
#define RT_USING_DEV_BUS
|
||||
#define RT_USING_PIN
|
||||
|
||||
@@ -263,6 +274,16 @@
|
||||
#define PKG_SQLITE_SQL_MAX_LEN 1024
|
||||
#define PKG_SQLITE_DB_NAME_MAX_LEN 64
|
||||
#define PKG_USING_SQLITE_V3193
|
||||
#define PKG_USING_LITTLEFS
|
||||
#define PKG_USING_LITTLEFS_V2112
|
||||
#define LFS_READ_SIZE 256
|
||||
#define LFS_PROG_SIZE 256
|
||||
#define LFS_BLOCK_SIZE 4096
|
||||
#define LFS_CACHE_SIZE 256
|
||||
#define LFS_BLOCK_CYCLES 500
|
||||
#define LFS_THREADSAFE
|
||||
#define LFS_LOOKAHEAD_MAX 128
|
||||
#define RT_DEF_LFS_DRIVERS 2
|
||||
/* end of system packages */
|
||||
|
||||
/* peripheral libraries and drivers */
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
/* Automatically generated file; DO NOT EDIT. */
|
||||
/* RT-Thread pre-include file */
|
||||
|
||||
#define LFS_CONFIG lfs_config.h
|
||||
#define RT_USING_LIBC
|
||||
#define RT_USING_NEWLIBC
|
||||
#define _POSIX_C_SOURCE 1
|
||||
|
||||
Reference in new issue
Block a user