Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions .build-test-rules.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,22 +79,26 @@ esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel:
- if: ((IDF_VERSION_MAJOR == 5 and IDF_VERSION_MINOR >= 3) or (IDF_VERSION_MAJOR > 5)) and (IDF_TARGET in ["esp32", "esp32c3"])
reason: Example is meant to be run under QEMU, which currently only supports ESP32 and ESP32-C3

spi_nand_flash/examples/nand_flash:
disable:
- if: IDF_VERSION_MAJOR < 5
reason: The spi_nand_flash component is compatible with IDF version v5.0 and above, due to a change in the f_mkfs API in versions above v5.0, which is not supported in older IDF versions.

spi_nand_flash/test_app:
disable:
- if: IDF_VERSION_MAJOR < 5
reason: The spi_nand_flash component is compatible with IDF version v5.0 and above, due to a change in the f_mkfs API in versions above v5.0, which is not supported in older IDF versions.
- if: IDF_VERSION_MAJOR < 6 and CONFIG_NAME == "bdl"
reason: BDL support requires the esp_blockdev interface, available starting from IDF version v6.0.

spi_nand_flash/host_test:
enable:
- if: IDF_TARGET == "linux"
disable:
- if: IDF_VERSION_MAJOR <= 5 and IDF_VERSION_MINOR < 3
reason: The spi_nand_flash component is compatible with IDF version v5.0 and above, due to a change in the f_mkfs API in versions above v5.0, which is not supported in older IDF versions.

spi_nand_flash_vfs/examples/nand_flash:
disable:
- if: IDF_VERSION_MAJOR < 5
reason: The spi_nand_flash component is compatible with IDF version v5.0 and above, due to a change in the f_mkfs API in versions above v5.0, which is not supported in older IDF versions.

spi_nand_flash_vfs/examples/nand_flash_bdl:
disable:
- if: IDF_VERSION_MAJOR == 5 and (IDF_VERSION_MINOR < 3)
reason: Fails to build on older versions of IDF
- if: IDF_VERSION_MAJOR < 6
reason: BDL support requires the esp_blockdev interface, available starting from IDF version v6.0.
1 change: 1 addition & 0 deletions .github/ISSUE_TEMPLATE/bug-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ body:
- quirc
- sh2lib
- spi_nand_flash
- spi_nand_flash_vfs
- supertinycron
- thorvg
- touch_element
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/upload_component.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ jobs:
quirc
sh2lib
spi_nand_flash
spi_nand_flash_vfs
supertinycron
thorvg
touch_element
Expand Down
5 changes: 4 additions & 1 deletion .idf_build_apps.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,8 @@ check_warnings = true

# build related options
build_dir = "build_@t_@w"
config = ["sdkconfig.ci","sdkconfig.ci.*="]
config_rules = [
'sdkconfig.ci=default',
'sdkconfig.ci.*=',
]
ignore_warning_file = ".ignore_build_warnings.txt"
68 changes: 68 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
from _pytest.fixtures import FixtureRequest
from pytest_embedded.plugin import multi_dut_argument, multi_dut_fixture
import pytest
import os
import logging
import typing as t

@pytest.hookimpl(tryfirst=True) # run early
def pytest_ignore_collect(collection_path, config):
Expand All @@ -14,3 +19,66 @@ def pytest_ignore_collect(collection_path, config):
return True

return False

@pytest.fixture
@multi_dut_argument
def config(request: FixtureRequest) -> str:
"""Fixture that provides the configuration for tests.
:param request: Pytest fixture request
:returns: Configuration string, defaults to 'default' if not specified
"""
return getattr(request, 'param', None) or 'default'



@pytest.fixture
@multi_dut_fixture
def build_dir(
request: FixtureRequest,
app_path: str,
target: t.Optional[str],
config: t.Optional[str],
) -> str:
"""Find a valid build directory based on priority rules.
Checks local build directories in the following order:
1. build_<target>_<config>
2. build_<target>
3. build_<config>
4. build
:param request: Pytest fixture request
:param app_path: Path to the application
:param target: Target being used
:param config: Configuration being used
:returns: Valid build directory name, or skips the test if no build directory is found
"""
check_dirs = []
build_dir_arg = request.config.getoption('build_dir')

if build_dir_arg:
check_dirs.append(build_dir_arg)
if target is not None and config is not None:
check_dirs.append(f'build_{target}_{config}')
if target is not None:
check_dirs.append(f'build_{target}')
if config is not None:
check_dirs.append(f'build_{config}')
check_dirs.append('build')

for check_dir in check_dirs:
binary_path = os.path.join(app_path, check_dir)
if os.path.isdir(binary_path):
logging.info(f'Found valid binary path: {binary_path}')
return check_dir

logging.warning('Checking binary path: %s... missing... trying another location', binary_path)

pytest.skip(
f'No valid build directory found (checked: {", ".join(check_dirs)}). '
f'Build the binary via "idf.py -B {check_dirs[0]} build" to enable this test.'
)
3 changes: 3 additions & 0 deletions spi_nand_flash/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## [1.0.0]
- feat: added block device support, which is available from IDF version v6.0

## [0.18.0]
- fix: Update esp_vfs_fat_register prototype to esp_vfs_fat_register_cfg to align with ESP-IDF v6.0.
The cfg version is now the primary API and remains aliased for compatibility.
Expand Down
46 changes: 26 additions & 20 deletions spi_nand_flash/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,32 +1,38 @@
idf_build_get_property(target IDF_TARGET)

set(reqs fatfs)
set(inc diskio include)
set(reqs)
set(inc include)
set(priv_inc priv_include)
set(srcs "src/nand.c"
"src/dhara_glue.c"
"src/nand_impl_wrap.c"
"diskio/diskio_nand.c")
"src/nand_impl_wrap.c")

if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" GREATER_EQUAL "6.0")
list(APPEND reqs esp_blockdev)
if(CONFIG_NAND_FLASH_ENABLE_BDL)
list(APPEND srcs "src/nand_flash_blockdev.c"
"src/nand_wl_blockdev.c")
endif()
endif()

if(${target} STREQUAL "linux")
list(APPEND srcs "src/nand_impl_linux.c"
"src/nand_linux_mmap_emul.c")
"src/nand_linux_mmap_emul.c"
"src/spi_nand_flash_test_helpers.c")
else()
list(APPEND srcs "src/nand_winbond.c"
"src/nand_gigadevice.c"
"src/nand_alliance.c"
"src/nand_micron.c"
"src/nand_zetta.c"
"src/nand_xtx.c"
"src/nand_impl.c"
"src/nand_impl_wrap.c"
"src/nand_diag_api.c"
"src/spi_nand_oper.c"
"vfs/vfs_fat_spinandflash.c")

set(priv_reqs vfs esp_mm)
list(APPEND inc vfs)

list(APPEND srcs "src/devices/nand_winbond.c"
"src/devices/nand_gigadevice.c"
"src/devices/nand_alliance.c"
"src/devices/nand_micron.c"
"src/devices/nand_zetta.c"
"src/devices/nand_xtx.c"
"src/nand_impl.c"
"src/nand_diag_api.c"
"src/spi_nand_flash_test_helpers.c"
"src/spi_nand_oper.c")

set(priv_reqs esp_mm)

if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "5.3")
list(APPEND reqs esp_driver_spi)
else()
Expand Down
16 changes: 16 additions & 0 deletions spi_nand_flash/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,26 @@ menu "SPI NAND Flash configuration"
back and verified. This can catch hardware problems with SPI NAND flash, or flash which
was not erased before verification.

config NAND_FLASH_ENABLE_BDL
bool "Enable Block Device Layer (BDL) support"
depends on IDF_INIT_VERSION >= "6.0"
default n
help
Enable Block Device Layer (BDL) support for SPI NAND Flash. This provides:
- Standard esp_blockdev_t interface for layered architecture
- Flash Block Device Layer (raw NAND flash access)
- Wear-Leveling Block Device Layer (logical sector access with wear leveling)
- Advanced layered API (spi_nand_flash_init_with_layers)
When disabled, only the legacy API is available.

Note: This option requires ESP-IDF >= 6.0 (esp_blockdev component).
Enabling this on ESP-IDF < 6.0 will result in a build error.

config NAND_ENABLE_STATS
bool "Host test statistics enabled"
depends on IDF_TARGET_LINUX
default n
help
This option enables gathering host test statistics and SPI NAND flash wear levelling simulation.

endmenu
56 changes: 39 additions & 17 deletions spi_nand_flash/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,37 +20,59 @@ SPI NAND Flash combines the benefits of NAND Flash technology with the simplicit

### Implementation Architecture

The component now features a layered architecture for better maintainability and modularity:

```mermaid
graph TD
A[Application] --> B[FATFS]
B --> C[Dhara Library]
C --> Hardware_Path[Hardware Path]
C --> Linux_Path[Linux Path]

subgraph Hardware_Path [Hardware Path]
HP1[NAND Flash Layer]
HP1 --> HP2[SPI NAND Flash Driver]
HP2 --> HP3["SPI Driver (ESP-IDF)"]
HP3 --> HP4[Hardware via SPI]
A[Application/FS] --> B[SPI NAND Flash API]
B --> C[NAND Wear-Leveling BDL]
C --> D[NAND Flash BDL]
D --> E{Target}
E -->|ESP Chips| F[SPI NAND Operations]
F --> G[Hardware via SPI]
E -->|Linux| H[NAND Emulation]
H --> I[Memory-Mapped File]

subgraph "Layered Architecture"
B["spi_nand_flash.h<br/>(Backward Compatible)"]
C["nand_wl_bdl<br/>(Wear Leveling)"]
D["nand_flash_bdl<br/>(Physical Flash)"]
end

subgraph Linux_Path [Linux Path]
LP1[NAND Flash Layer]
LP1 --> LP2[NAND Emulation Layer]
LP2 --> LP3[Memory Mapped File]

subgraph "Hardware Layer"
F["spi_nand_oper<br/>(SPI Commands)"]
H["nand_linux_mmap_emul<br/>(Host Test)"]
end
```

**Key Benefits:**
- **Backward Compatible**: Existing code works unchanged; sector-named APIs are retained as aliases of the page API
- **Page terminology**: Public API uses *page* (read_page, write_page, get_page_count, get_page_size) to align with NAND flash; sector names remain for compatibility
- **Modular Design**: Clear separation between wear-leveling and flash management
- **Enhanced Features**: Direct access to flash and wear-leveling layers

**📖 Architecture Documentation:**
For detailed information about the layered architecture, implementation details, API usage, and migration guide, see:
- [Layered Architecture Guide](layered_architecture.md) - Complete architecture documentation

## Supported SPI NAND Flash chips

At present, `spi_nand_flash` component is compatible with the chips produced by the following manufacturers and and their respective model numbers:

* Winbond - W25N01GVxxxG/T/R, W25N512GVxIG/IT, W25N512GWxxR/T, W25N01JWxxxG/T, W25N01JWxxxG/T, W25N02KVxxIR/U, W25N04KVxxIR/U
* Gigadevice - GD5F1GQ5UExxG, GD5F1GQ5RExxG, GD5F2GQ5UExxG, GD5F2GQ5RExxG, GD5F2GM7xExxG, GD5F4GQ6UExxG, GD5F4GQ6RExxG, GD5F4GQ6UExxG, GD5F4GQ6RExxG, GD5F4GM8xExxG
* Winbond - W25N01GVxxxG/T/R, W25N512GVxIG/IT, W25N512GWxxR/T, W25N01JWxxxG/T, W25N02KVxxIR/U, W25N04KVxxIR/U
* Gigadevice - GD5F1GQ5UExxG, GD5F1GQ5RExxG, GD5F2GQ5UExxG, GD5F2GQ5RExxG, GD5F2GM7xExxG, GD5F4GQ6UExxG, GD5F4GQ6RExxG, GD5F4GM8xExxG
* Alliance - AS5F31G04SND-08LIN, AS5F32G04SND-08LIN, AS5F12G04SND-10LIN, AS5F34G04SND-08LIN, AS5F14G04SND-10LIN, AS5F38G04SND-08LIN, AS5F18G04SND-10LIN
* Micron - MT29F4G01ABAFDWB, MT29F1G01ABAFDSF-AAT:F, MT29F2G01ABAGDWB-IT:G
* Zetta - ZD35Q1GC
* XTX - XT26G08D

## FATFS Integration

For FATFS filesystem support, use the separate [`spi_nand_flash_vfs`](../spi_nand_flash_vfs) component:
- Provides diskio adapters and VFS mount helpers
- Supports both legacy API and BDL API
- See [`spi_nand_flash_vfs/README.md`](../spi_nand_flash_vfs/README.md) for usage examples

## Troubleshooting

To verify SPI NAND Flash writes, enable the `NAND_FLASH_VERIFY_WRITE` option in menuconfig. When this option is enabled, every time data is written to the SPI NAND Flash, it will be read back and verified. This helps in identifying hardware issues with the SPI NAND Flash.
Expand Down
4 changes: 0 additions & 4 deletions spi_nand_flash/examples/nand_flash/main/idf_component.yml

This file was deleted.

10 changes: 0 additions & 10 deletions spi_nand_flash/examples/nand_flash/pytest_nand_flash_example.py

This file was deleted.

This file was deleted.

42 changes: 35 additions & 7 deletions spi_nand_flash/host_test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,49 @@ nand_mmap_emul_config_t cfg = {

### Usage Example:

#### Option 1: Direct Device API
```c
// Initialize with custom settings
nand_mmap_emul_config_t cfg = {
nand_file_mmap_emul_config_t cfg = {
.flash_file_name = "/tmp/my_nand.bin",
.flash_file_size = 1024 * 1024, // 1MB
.flash_file_size = 50 * 1024 * 1024, // 50MB
.keep_dump = false
};
spi_nand_flash_config_t nand_flash_config = {.emul_conf = &cfg};
spi_nand_flash_config_t nand_flash_config = {&cfg, 0, SPI_NAND_IO_MODE_SIO, 0};

// Initialize nand_flash with NAND emulation parameter
// Initialize NAND flash with emulation
spi_nand_flash_device_t *handle;
spi_nand_flash_init_device(&nand_flash_config, &handle)
spi_nand_flash_init_device(&nand_flash_config, &handle);

// Use direct NAND operations (page API preferred; sector API is also supported)
uint32_t page_size;
spi_nand_flash_get_page_size(handle, &page_size);
uint8_t *buffer = malloc(page_size);
uint32_t page_id = 0;
spi_nand_flash_read_page(handle, buffer, page_id);
spi_nand_flash_write_page(handle, buffer, page_id);

// Cleanup
spi_nand_flash_deinit_device(handle);
```

#### Option 2: Block Device API
```c
// Initialize with block device interface
nand_file_mmap_emul_config_t cfg = {"", 50 * 1024 * 1024, false};
spi_nand_flash_config_t nand_flash_config = {&cfg, 0, SPI_NAND_IO_MODE_SIO, 0};

spi_nand_flash_device_t *device_handle;
esp_blockdev_handle_t nand_bdl;

// Create Flash Block Device Layer
nand_flash_get_blockdev(&nand_flash_config, &device_handle, &nand_bdl);

// Use NAND operations...
// Use block device operations
uint32_t page_size = nand_bdl->geometry.read_size; // BDL geometry uses page size
nand_bdl->ops->read(nand_bdl, buffer, page_size, offset, size);
nand_bdl->ops->write(nand_bdl, buffer, offset, size);

// Cleanup
ESP_ERROR_CHECK(spi_nand_flash_deinit_device(handle));
nand_bdl->ops->release(nand_bdl);
```
Loading
Loading