Skip to content

Commit 4945546

Browse files
tmediccixiaoxiang781216
authored andcommitted
benchmark/mtd: Add MTD testing/benchmark application
This test allows measuring write and read operations on an MTD flash device, evaluating its transfer rates. Signed-off-by: Tiago Medicci <[email protected]>
1 parent cdc5968 commit 4945546

File tree

5 files changed

+317
-0
lines changed

5 files changed

+317
-0
lines changed

benchmarks/mtd/CMakeLists.txt

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# ##############################################################################
2+
# apps/benchmarks/mtd/CMakeLists.txt
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
# Licensed to the Apache Software Foundation (ASF) under one or more contributor
7+
# license agreements. See the NOTICE file distributed with this work for
8+
# additional information regarding copyright ownership. The ASF licenses this
9+
# file to you under the Apache License, Version 2.0 (the "License"); you may not
10+
# use this file except in compliance with the License. You may obtain a copy of
11+
# the License at
12+
#
13+
# http://www.apache.org/licenses/LICENSE-2.0
14+
#
15+
# Unless required by applicable law or agreed to in writing, software
16+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18+
# License for the specific language governing permissions and limitations under
19+
# the License.
20+
#
21+
# ##############################################################################
22+
23+
if(CONFIG_BENCHMARK_MTD)
24+
nuttx_add_application(
25+
NAME
26+
mtd
27+
STACKSIZE
28+
${CONFIG_DEFAULT_TASK_STACKSIZE}
29+
MODULE
30+
${CONFIG_BENCHMARK_MTD}
31+
SRCS
32+
mtd.c)
33+
endif()

benchmarks/mtd/Kconfig

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#
2+
# For a description of the syntax of this configuration file,
3+
# see the file kconfig-language.txt in the NuttX tools repository.
4+
#
5+
6+
config BENCHMARK_MTD
7+
tristate "MTD test and transfer rate benchmark"
8+
default n
9+
depends on BUILD_FLAT && MTD
10+
---help---
11+
This testing/benchmark application performs an erase/write
12+
operation to evaluate write transfer rate and then reads the
13+
written content back to evaluate the read transfer rate. Finally,
14+
it compares the read data with the previously written data to
15+
ensure the MTD device is working as expected.
16+
17+
NOTE: This application uses internal OS interfaces and so it is not
18+
available in the NuttX kernel build.

benchmarks/mtd/Make.defs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
############################################################################
2+
# apps/benchmarks/mtd/Make.defs
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
# Licensed to the Apache Software Foundation (ASF) under one or more
7+
# contributor license agreements. See the NOTICE file distributed with
8+
# this work for additional information regarding copyright ownership. The
9+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
10+
# "License"); you may not use this file except in compliance with the
11+
# License. You may obtain a copy of the License at
12+
#
13+
# http://www.apache.org/licenses/LICENSE-2.0
14+
#
15+
# Unless required by applicable law or agreed to in writing, software
16+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18+
# License for the specific language governing permissions and limitations
19+
# under the License.
20+
#
21+
############################################################################
22+
23+
ifneq ($(CONFIG_BENCHMARK_MTD),)
24+
CONFIGURED_APPS += $(APPDIR)/benchmarks/mtd/
25+
endif

benchmarks/mtd/Makefile

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
############################################################################
2+
# apps/benchmarks/mtd/Makefile
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
# Licensed to the Apache Software Foundation (ASF) under one or more
7+
# contributor license agreements. See the NOTICE file distributed with
8+
# this work for additional information regarding copyright ownership. The
9+
# ASF licenses this file to you under the Apache License, Version 2.0 (the
10+
# "License"); you may not use this file except in compliance with the
11+
# License. You may obtain a copy of the License at
12+
#
13+
# http://www.apache.org/licenses/LICENSE-2.0
14+
#
15+
# Unless required by applicable law or agreed to in writing, software
16+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18+
# License for the specific language governing permissions and limitations
19+
# under the License.
20+
#
21+
############################################################################
22+
23+
include $(APPDIR)/Make.defs
24+
25+
# MTD test and transfer rate benchmark
26+
27+
PROGNAME = mtd
28+
PRIORITY = SCHED_PRIORITY_DEFAULT
29+
STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE)
30+
MODULE = $(CONFIG_BENCHMARK_MTD)
31+
32+
MAINSRC = mtd.c
33+
34+
include $(APPDIR)/Application.mk

benchmarks/mtd/mtd.c

+207
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
/****************************************************************************
2+
* apps/benchmarks/mtd/mtd.c
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Licensed to the Apache Software Foundation (ASF) under one or more
7+
* contributor license agreements. See the NOTICE file distributed with
8+
* this work for additional information regarding copyright ownership. The
9+
* ASF licenses this file to you under the Apache License, Version 2.0 (the
10+
* "License"); you may not use this file except in compliance with the
11+
* License. You may obtain a copy of the License at
12+
*
13+
* http://www.apache.org/licenses/LICENSE-2.0
14+
*
15+
* Unless required by applicable law or agreed to in writing, software
16+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
17+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
18+
* License for the specific language governing permissions and limitations
19+
* under the License.
20+
*
21+
****************************************************************************/
22+
23+
/****************************************************************************
24+
* Included Files
25+
****************************************************************************/
26+
27+
#include <nuttx/config.h>
28+
29+
#include <sys/stat.h>
30+
#include <unistd.h>
31+
#include <stdio.h>
32+
#include <stdlib.h>
33+
#include <string.h>
34+
#include <time.h>
35+
36+
#include <nuttx/mtd/mtd.h>
37+
#include <nuttx/fs/smart.h>
38+
#include <nuttx/fs/ioctl.h>
39+
40+
/****************************************************************************
41+
* Pre-processor Definitions
42+
****************************************************************************/
43+
44+
/****************************************************************************
45+
* Private data
46+
****************************************************************************/
47+
48+
/****************************************************************************
49+
* Public Functions
50+
****************************************************************************/
51+
52+
int main(int argc, FAR char *argv[])
53+
{
54+
struct inode *inode;
55+
struct timespec start;
56+
struct timespec end;
57+
struct mtd_geometry_s geo;
58+
struct partition_info_s info;
59+
int ret;
60+
int x;
61+
double elapsed_time;
62+
double transfer_rate;
63+
size_t total_bytes_written = 0;
64+
size_t total_bytes_read = 0;
65+
char *buffer;
66+
67+
/* Argument given? */
68+
69+
if (argc < 2)
70+
{
71+
fprintf(stderr, "usage: mtd flash_block_device\n");
72+
return -1;
73+
}
74+
75+
/* Find the inode of the block driver identified by 'source' */
76+
77+
ret = open_blockdriver(argv[1], 0, &inode);
78+
if (ret < 0)
79+
{
80+
fprintf(stderr, "Failed to open %s\n", argv[1]);
81+
return ret;
82+
}
83+
84+
/* Get the low-level format from the device. */
85+
86+
ret = inode->u.i_bops->ioctl(inode, BIOC_PARTINFO, (unsigned long) &info);
87+
if (ret != OK)
88+
{
89+
fprintf(stderr, "Device is not a block device\n");
90+
goto errout_with_driver;
91+
}
92+
93+
/* Get the MTD geometry */
94+
95+
ret = inode->u.i_bops->ioctl(inode, MTDIOC_GEOMETRY, (unsigned long) &geo);
96+
if (ret != OK)
97+
{
98+
fprintf(stderr, "Device is not a MTD device\n");
99+
goto errout_with_driver;
100+
}
101+
102+
/* Report the device structure */
103+
104+
printf("FLASH device parameters:\n");
105+
printf(" Sector size: %10d\n", info.sectorsize);
106+
printf(" Sector count: %10d\n", info.numsectors);
107+
printf(" Erase block: %10d\n", geo.erasesize);
108+
printf(" Total size: %10d\n", info.sectorsize * info.numsectors);
109+
110+
if (info.sectorsize != geo.erasesize)
111+
{
112+
fprintf(stderr, "Sector size does not match the erase block size.\n"
113+
"Please adjust the sector size to enable erasing and writing "
114+
"without using an intermediary read buffer.\n");
115+
goto errout_with_driver;
116+
}
117+
118+
/* Allocate buffers to use */
119+
120+
buffer = (char *)malloc(info.sectorsize);
121+
if (buffer == NULL)
122+
{
123+
fprintf(stderr, "Error allocating buffer\n");
124+
goto errout_with_driver;
125+
}
126+
127+
/* Fill the buffer with known data and print it in hex format */
128+
129+
for (int i = 0; i < info.sectorsize; i++)
130+
{
131+
buffer[i] = (char)(i & 0xff);
132+
}
133+
134+
/* Now write some data to the sector */
135+
136+
printf("\nStarting write operation...\n");
137+
138+
clock_gettime(CLOCK_MONOTONIC, &start);
139+
for (x = 0; x < info.numsectors; x++)
140+
{
141+
inode->u.i_bops->write(inode, (const unsigned char *)buffer, x, 1);
142+
143+
total_bytes_written += info.sectorsize;
144+
}
145+
146+
clock_gettime(CLOCK_MONOTONIC, &end);
147+
148+
elapsed_time = (end.tv_sec - start.tv_sec) + \
149+
(end.tv_nsec - start.tv_nsec) / 1e9;
150+
transfer_rate = (total_bytes_written / elapsed_time) / 1024;
151+
152+
printf("\nWrite operation completed in %.2f seconds\n", elapsed_time);
153+
printf("Total bytes written: %zu\n", total_bytes_written);
154+
printf("Transfer rate [write]: %.2f KiB/s\n", transfer_rate);
155+
156+
/* Now read the data back to validate everything was written and can
157+
* be read.
158+
*/
159+
160+
printf("\nStarting read operation...\n");
161+
162+
clock_gettime(CLOCK_MONOTONIC, &start);
163+
164+
for (x = 0; x < info.numsectors; x++)
165+
{
166+
inode->u.i_bops->read(inode, (unsigned char *)buffer, x, 1);
167+
168+
total_bytes_read += info.sectorsize;
169+
}
170+
171+
clock_gettime(CLOCK_MONOTONIC, &end);
172+
173+
elapsed_time = (end.tv_sec - start.tv_sec) + \
174+
(end.tv_nsec - start.tv_nsec) / 1e9;
175+
transfer_rate = (total_bytes_written / elapsed_time) / 1024;
176+
177+
printf("\nRead operation completed in %.2f seconds\n", elapsed_time);
178+
printf("Total bytes read: %zu\n", total_bytes_read);
179+
printf("Transfer rate [read]: %.2f KiB/s\n", transfer_rate);
180+
181+
/* Compare the read data with the written data */
182+
183+
for (int i = 0; i < info.sectorsize; i++)
184+
{
185+
if (buffer[i] != (char)(i & 0xff))
186+
{
187+
printf("\nData mismatch at byte %d: expected %02X, got %02X\n",
188+
i, (unsigned char)(i & 0xff), (unsigned char)buffer[i]);
189+
goto errout_with_buffers;
190+
}
191+
}
192+
193+
printf("\nData verification successful: read data matches written data\n");
194+
195+
errout_with_buffers:
196+
197+
/* Free the allocated buffers */
198+
199+
free(buffer);
200+
201+
errout_with_driver:
202+
203+
/* Now close the block device and exit */
204+
205+
close_blockdriver(inode);
206+
return 0;
207+
}

0 commit comments

Comments
 (0)