Skip to content

Commit 69e8bbd

Browse files
committed
feat(spi_nand_flash): update test_app, host_tests and documentation for block device support
1 parent b159731 commit 69e8bbd

File tree

8 files changed

+810
-30
lines changed

8 files changed

+810
-30
lines changed

.build-test-rules.yml

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -76,20 +76,17 @@ esp_lcd_qemu_rgb/examples/lcd_qemu_rgb_panel:
7676

7777
spi_nand_flash/examples/nand_flash:
7878
disable:
79-
- if: IDF_VERSION_MAJOR < 5
80-
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.
79+
- if: IDF_VERSION_MAJOR < 6
80+
reason: The spi_nand_flash component uses the esp_blockdev interface, which is supported starting from IDF version v6.0. It is not available in older IDF versions.
8181

8282
spi_nand_flash/test_app:
8383
disable:
84-
- if: IDF_VERSION_MAJOR < 5
85-
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.
84+
- if: IDF_VERSION_MAJOR < 6
85+
reason: The spi_nand_flash component uses the esp_blockdev interface, which is supported starting from IDF version v6.0. It is not available in older IDF versions.
8686

8787
spi_nand_flash/host_test:
8888
enable:
8989
- if: IDF_TARGET == "linux"
9090
disable:
91-
- if: IDF_VERSION_MAJOR < 5
92-
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.
93-
disable:
94-
- if: IDF_VERSION_MAJOR == 5 and (IDF_VERSION_MINOR < 3)
95-
reason: Fails to build on older versions of IDF
91+
- if: IDF_VERSION_MAJOR < 6
92+
reason: The spi_nand_flash component uses the esp_blockdev interface, which is supported starting from IDF version v6.0. It is not available in older IDF versions.

spi_nand_flash/host_test/README.md

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,44 @@ nand_mmap_emul_config_t cfg = {
3434

3535
### Usage Example:
3636

37+
#### Option 1: Direct Device API
3738
```c
3839
// Initialize with custom settings
39-
nand_mmap_emul_config_t cfg = {
40+
nand_file_mmap_emul_config_t cfg = {
4041
.flash_file_name = "/tmp/my_nand.bin",
41-
.flash_file_size = 1024 * 1024, // 1MB
42+
.flash_file_size = 50 * 1024 * 1024, // 50MB
4243
.keep_dump = false
4344
};
44-
spi_nand_flash_config_t nand_flash_config = {.emul_conf = &cfg};
45+
spi_nand_flash_config_t nand_flash_config = {&cfg, 0, SPI_NAND_IO_MODE_SIO, 0};
4546

46-
// Initialize nand_flash with NAND emulation parameter
47+
// Initialize NAND flash with emulation
4748
spi_nand_flash_device_t *handle;
48-
spi_nand_flash_init_device(&nand_flash_config, &handle)
49+
spi_nand_flash_init_device(&nand_flash_config, &handle);
50+
51+
// Use direct NAND operations
52+
spi_nand_flash_read_sector(handle, buffer, sector_id);
53+
spi_nand_flash_write_sector(handle, buffer, sector_id);
54+
55+
// Cleanup
56+
spi_nand_flash_deinit_device(handle);
57+
```
58+
59+
#### Option 2: Block Device API
60+
```c
61+
// Initialize with block device interface
62+
nand_file_mmap_emul_config_t cfg = {"", 50 * 1024 * 1024, false};
63+
spi_nand_flash_config_t nand_flash_config = {&cfg, 0, SPI_NAND_IO_MODE_SIO, 0};
64+
65+
spi_nand_flash_device_t *device_handle;
66+
esp_blockdev_handle_t nand_bdl;
67+
68+
// Create Flash Block Device Layer
69+
nand_flash_get_blockdev(&nand_flash_config, &device_handle, &nand_bdl);
4970
50-
// Use NAND operations...
71+
// Use block device operations
72+
nand_bdl->ops->read(nand_bdl, buffer, sector_size, offset, size);
73+
nand_bdl->ops->write(nand_bdl, buffer, offset, size);
5174
5275
// Cleanup
53-
ESP_ERROR_CHECK(spi_nand_flash_deinit_device(handle));
76+
nand_bdl->ops->release(nand_bdl);
5477
```

spi_nand_flash/host_test/main/test_nand_flash.cpp

Lines changed: 96 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,34 @@
1010
#include "spi_nand_flash.h"
1111
#include "nand_linux_mmap_emul.h"
1212
#include "nand_private/nand_impl_wrap.h"
13+
#include "esp_blockdev.h"
14+
#include "esp_nand_blockdev.h"
1315

1416
#include <catch2/catch_test_macros.hpp>
1517

1618
#define PATTERN_SEED 0x12345678
1719

20+
static void fill_buffer(uint32_t seed, uint8_t *dst, size_t count)
21+
{
22+
srand(seed);
23+
for (size_t i = 0; i < count; ++i) {
24+
uint32_t val = rand();
25+
memcpy(dst + i * sizeof(uint32_t), &val, sizeof(val));
26+
}
27+
}
28+
29+
static void check_buffer(uint32_t seed, const uint8_t *src, size_t count)
30+
{
31+
srand(seed);
32+
for (size_t i = 0; i < count; ++i) {
33+
uint32_t val;
34+
memcpy(&val, src + i * sizeof(uint32_t), sizeof(val));
35+
if (!(rand() == val)) {
36+
printf("Val not equal\n");
37+
}
38+
}
39+
}
40+
1841
TEST_CASE("verify mark_bad_block works", "[spi_nand_flash]")
1942
{
2043
nand_file_mmap_emul_config_t conf = {"", 50 * 1024 * 1024, true};
@@ -42,15 +65,6 @@ TEST_CASE("verify mark_bad_block works", "[spi_nand_flash]")
4265
spi_nand_flash_deinit_device(device_handle);
4366
}
4467

45-
static void fill_buffer(uint32_t seed, uint8_t *dst, size_t count)
46-
{
47-
srand(seed);
48-
for (size_t i = 0; i < count; ++i) {
49-
uint32_t val = rand();
50-
memcpy(dst + i * sizeof(uint32_t), &val, sizeof(val));
51-
}
52-
}
53-
5468
TEST_CASE("verify nand_prog, nand_read, nand_copy, nand_is_free works", "[spi_nand_flash]")
5569
{
5670
nand_file_mmap_emul_config_t conf = {"", 50 * 1024 * 1024, false};
@@ -85,10 +99,83 @@ TEST_CASE("verify nand_prog, nand_read, nand_copy, nand_is_free works", "[spi_na
8599
REQUIRE(is_page_free == false);
86100

87101
REQUIRE(nand_wrap_read(device_handle, test_page, 0, sector_size, temp_buf) == 0);
102+
check_buffer(PATTERN_SEED, temp_buf, sector_size / sizeof(uint32_t));
103+
88104
REQUIRE(nand_wrap_copy(device_handle, test_page, dst_page) == 0);
105+
89106
REQUIRE(nand_wrap_read(device_handle, dst_page, 0, sector_size, temp_buf) == 0);
107+
check_buffer(PATTERN_SEED, temp_buf, sector_size / sizeof(uint32_t));
90108
}
91109
free(pattern_buf);
92110
free(temp_buf);
93111
spi_nand_flash_deinit_device(device_handle);
94112
}
113+
114+
TEST_CASE("verify mark_bad_block works with bdl interface", "[spi_nand_flash]")
115+
{
116+
nand_file_mmap_emul_config_t conf = {"", 50 * 1024 * 1024, true};
117+
spi_nand_flash_config_t nand_flash_config = {&conf, 0, SPI_NAND_IO_MODE_SIO, 0};
118+
spi_nand_flash_device_t *device_handle;
119+
esp_blockdev_handle_t nand_bdl;
120+
REQUIRE(nand_flash_get_blockdev(&nand_flash_config, &device_handle, &nand_bdl) == 0);
121+
122+
uint32_t block_size = nand_bdl->geometry.erase_size;
123+
uint32_t block_num = nand_bdl->geometry.disk_size / block_size;
124+
125+
uint32_t test_block = 15;
126+
if (test_block < block_num) {
127+
REQUIRE(nand_bdl->ops->erase(nand_bdl, test_block * block_size, block_size) == 0);
128+
// Verify if test_block is not bad block
129+
esp_blockdev_cmd_arg_is_bad_block_t bad_block_status = {test_block, false};
130+
REQUIRE(nand_bdl->ops->ioctl(nand_bdl, ESP_BLOCKDEV_CMD_IS_BAD_BLOCK, &bad_block_status) == 0);
131+
REQUIRE(bad_block_status.status == false);
132+
// mark test_block as a bad block
133+
uint32_t block = test_block;
134+
REQUIRE(nand_bdl->ops->ioctl(nand_bdl, ESP_BLOCKDEV_CMD_MARK_BAD_BLOCK, &block) == 0);
135+
// Verify if test_block is marked as bad block
136+
REQUIRE(nand_bdl->ops->ioctl(nand_bdl, ESP_BLOCKDEV_CMD_IS_BAD_BLOCK, &bad_block_status) == 0);
137+
REQUIRE(bad_block_status.status == true);
138+
}
139+
140+
nand_bdl->ops->release(nand_bdl);
141+
}
142+
143+
TEST_CASE("verify nand_prog, nand_read, nand_copy, nand_is_free works with bdl interface", "[spi_nand_flash]")
144+
{
145+
nand_file_mmap_emul_config_t conf = {"", 50 * 1024 * 1024, false};
146+
spi_nand_flash_config_t nand_flash_config = {&conf, 0, SPI_NAND_IO_MODE_SIO, 0};
147+
spi_nand_flash_device_t *device_handle;
148+
esp_blockdev_handle_t nand_bdl;
149+
REQUIRE(nand_flash_get_blockdev(&nand_flash_config, &device_handle, &nand_bdl) == 0);
150+
151+
uint32_t block_size = nand_bdl->geometry.erase_size;
152+
uint32_t sector_size = nand_bdl->geometry.write_size;
153+
uint32_t sector_num = nand_bdl->geometry.disk_size / sector_size;
154+
155+
uint8_t *pattern_buf = (uint8_t *)malloc(sector_size);
156+
REQUIRE(pattern_buf != NULL);
157+
uint8_t *temp_buf = (uint8_t *)malloc(sector_size);
158+
REQUIRE(temp_buf != NULL);
159+
160+
fill_buffer(PATTERN_SEED, pattern_buf, sector_size / sizeof(uint32_t));
161+
162+
uint32_t test_block = 20;
163+
uint32_t test_page = test_block * (block_size / sector_size); //(block_num * pages_per_block)
164+
if (test_page < sector_num) {
165+
// Verify if test_page is free
166+
esp_blockdev_cmd_arg_is_free_page_t page_free_status = {test_page, true};
167+
REQUIRE(nand_bdl->ops->ioctl(nand_bdl, ESP_BLOCKDEV_CMD_IS_FREE_PAGE, &page_free_status) == 0);
168+
REQUIRE(page_free_status.status == true);
169+
// Write/program test_page
170+
REQUIRE(nand_bdl->ops->write(nand_bdl, pattern_buf, test_page * sector_size, sector_size) == 0);
171+
// Verify if test_page is used/programmed
172+
REQUIRE(nand_bdl->ops->ioctl(nand_bdl, ESP_BLOCKDEV_CMD_IS_FREE_PAGE, &page_free_status) == 0);
173+
REQUIRE(page_free_status.status == false);
174+
175+
REQUIRE(nand_bdl->ops->read(nand_bdl, temp_buf, sector_size, test_page * sector_size, sector_size) == 0);
176+
check_buffer(PATTERN_SEED, temp_buf, sector_size / sizeof(uint32_t));
177+
}
178+
free(pattern_buf);
179+
free(temp_buf);
180+
nand_bdl->ops->release(nand_bdl);
181+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
CONFIG_IDF_TARGET="linux"
12
CONFIG_COMPILER_CXX_EXCEPTIONS=y
23
CONFIG_MMU_PAGE_SIZE=0X10000
34
CONFIG_NAND_ENABLE_STATS=y

0 commit comments

Comments
 (0)