Skip to content

Commit d9846dc

Browse files
committed
drivers: flash: Added native POSIX flash driver
Added native POSIX flash driver that writes flash content to a binary file. Signed-off-by: Jan Van Winkel <jan.van_winkel@dxplore.eu>
1 parent 3f0d3cb commit d9846dc

File tree

7 files changed

+293
-1
lines changed

7 files changed

+293
-1
lines changed

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@
115115
/drivers/dma/*sam0* @Sizurka
116116
/drivers/ethernet/ @jukkar @tbursztyka @pfalcon
117117
/drivers/flash/ @nashif
118+
/drivers/flash/*native_posix* @vanwinkeljan
118119
/drivers/flash/*stm32* @superna9999
119120
/drivers/gpio/*ht16k33* @henrikbrixandersen
120121
/drivers/gpio/*stm32* @rsalveti @idlethread

boards/posix/native_posix/Kconfig.defconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,13 @@ config TRACING_CTF_BOTTOM_POSIX
8787

8888
endif # TRACING_CTF
8989

90+
if FLASH
91+
92+
config FLASH_NATIVE_POSIX
93+
default y
94+
95+
endif # FLASH
96+
9097
endif # BOARD_NATIVE_POSIX
9198

9299
if USB

boards/posix/native_posix/doc/index.rst

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,8 +533,29 @@ The following peripherals are currently provided with this board:
533533
.. _SDL2:
534534
https://www.libsdl.org/download-2.0.php
535535

536+
**Flash driver**:
537+
A flash driver is provided that accesses all flash data through a binary file
538+
on the host file system.
539+
540+
The size of the flash device can be configured through the native POSIX board
541+
device tree and the sector size is configurable via the Kconfig option
542+
:option:`CONFIG_FLASH_NATIVE_POSIX_SECTOR_SIZE`. The sector size will only be
543+
used to return flash page layout related information and no restrictions are
544+
imposed by the driver based on the configured sector size. As such an erase
545+
operation of arbitrary size will succeed on the emulated flash device.
546+
Further the emulated device will not impose any write restriction that are
547+
applicable for a regular flash device, including changing the state of a bit
548+
from zero to one.
549+
550+
By default the binary data is located in the file *flash.bin* in the current
551+
working directory. The location of this file can be changed through the
552+
command line parameter *--flash*. The flash data will be stored in raw format
553+
and the file will be truncated to match the size specified in the device tree
554+
configuration. In case the file does not exists the driver will take care of
555+
creating the file, else the existing file is used.
556+
536557
UART
537-
*****
558+
****
538559

539560
This driver can be configured with :option:`CONFIG_UART_NATIVE_POSIX`
540561
to instantiate up to two UARTs. By default only one UART is enabled.

drivers/flash/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_SAM0 flash_sam0.c)
1414
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_SAM flash_sam.c)
1515
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_NIOS2_QSPI soc_flash_nios2_qspi.c)
1616
zephyr_library_sources_ifdef(CONFIG_SOC_FLASH_GECKO flash_gecko.c)
17+
zephyr_library_sources_ifdef(CONFIG_FLASH_NATIVE_POSIX flash_native_posix.c)
1718

1819
if(CONFIG_CLOCK_CONTROL_STM32_CUBE)
1920
zephyr_sources(flash_stm32.c)

drivers/flash/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ source "drivers/flash/Kconfig.nios2_qspi"
5353

5454
source "drivers/flash/Kconfig.gecko"
5555

56+
source "drivers/flash/Kconfig.native_posix"
57+
5658
source "drivers/flash/Kconfig.nor"
5759

5860
source "drivers/flash/Kconfig.qmsi"

drivers/flash/Kconfig.native_posix

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Kconfig - Native POSIX Flash driver
2+
#
3+
# Copyright (c) 2019, Jan Van Winkel (jan.van_winkel@dxplore.eu)
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
menuconfig FLASH_NATIVE_POSIX
8+
bool
9+
prompt "Native POSIX Flash driver"
10+
select FLASH_HAS_DRIVER_ENABLED
11+
select FLASH_HAS_PAGE_LAYOUT
12+
depends on FLASH
13+
help
14+
Enable Native POSIX flash driver.
15+
16+
if FLASH_NATIVE_POSIX
17+
18+
config FLASH_NATIVE_POSIX_SECTOR_SIZE
19+
int "Sector size"
20+
default 8
21+
help
22+
This option specifies the sector size of the Native POSIX flash in KB
23+
24+
endif # FLASH_NATIVE_POSIX

drivers/flash/flash_native_posix.c

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
/*
2+
* Copyright (c) 2019 Jan Van Winkel <jan.van_winkel@dxplore.eu>
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <device.h>
8+
#include <flash.h>
9+
10+
#include <unistd.h>
11+
#include <sys/types.h>
12+
#include <sys/stat.h>
13+
#include <sys/mman.h>
14+
#include <fcntl.h>
15+
#include <string.h>
16+
#include <errno.h>
17+
18+
#include "cmdline.h"
19+
#include "soc.h"
20+
21+
#define LOG_LEVEL CONFIG_FLASH_LOG_LEVEL
22+
#include <logging/log.h>
23+
LOG_MODULE_REGISTER(flash_native_posix);
24+
25+
static const char default_flash_path[] = "flash.bin";
26+
27+
struct flash_native_posix_data {
28+
struct k_sem mutex;
29+
const char *flash_path;
30+
int fd;
31+
u8_t *flash;
32+
bool init_called;
33+
};
34+
35+
struct flash_native_posix_config {
36+
size_t flash_size;
37+
#if defined(CONFIG_FLASH_PAGE_LAYOUT)
38+
struct flash_pages_layout layout;
39+
#endif
40+
};
41+
42+
#define DEV_NAME(dev) ((dev)->config->name)
43+
#define DEV_CONFIG(dev) ((dev)->config->config_info)
44+
#define DEV_DATA(dev) \
45+
((struct flash_native_posix_data *const)(dev)->driver_data)
46+
47+
static int flash_native_posix_read(struct device *dev, off_t offset, void *data,
48+
size_t size)
49+
{
50+
struct flash_native_posix_data *const dev_data = DEV_DATA(dev);
51+
const struct flash_native_posix_config *config = DEV_CONFIG(dev);
52+
53+
if (dev_data->flash == MAP_FAILED) {
54+
LOG_ERR("No flash device mapped");
55+
return -EIO;
56+
}
57+
58+
if ((offset + size) > config->flash_size) {
59+
LOG_WRN("Reading outside of flash boundaries");
60+
return -EINVAL;
61+
}
62+
63+
memcpy(data, dev_data->flash + offset, size);
64+
65+
return 0;
66+
}
67+
68+
static int flash_native_posix_write(struct device *dev, off_t offset,
69+
const void *data, size_t size)
70+
{
71+
struct flash_native_posix_data *const dev_data = DEV_DATA(dev);
72+
const struct flash_native_posix_config *config = DEV_CONFIG(dev);
73+
74+
if (dev_data->flash == MAP_FAILED) {
75+
LOG_ERR("No flash device mapped");
76+
return -EIO;
77+
}
78+
79+
if ((offset + size) > config->flash_size) {
80+
LOG_WRN("Writing outside of flash boundaries");
81+
return -EINVAL;
82+
}
83+
84+
memcpy(dev_data->flash + offset, data, size);
85+
86+
return 0;
87+
}
88+
89+
static int flash_native_posix_erase(struct device *dev, off_t offset,
90+
size_t size)
91+
{
92+
struct flash_native_posix_data *const dev_data = DEV_DATA(dev);
93+
const struct flash_native_posix_config *config = DEV_CONFIG(dev);
94+
95+
if (dev_data->flash == MAP_FAILED) {
96+
LOG_ERR("No flash device mapped");
97+
return -EIO;
98+
}
99+
100+
if ((offset + size) > config->flash_size) {
101+
LOG_WRN("Erasing outside of flash boundaries");
102+
return -EINVAL;
103+
}
104+
105+
memset(dev_data->flash + offset, 0xff, size);
106+
107+
return 0;
108+
}
109+
110+
static int flash_native_posix_write_protection(struct device *dev, bool enable)
111+
{
112+
return 0;
113+
}
114+
115+
#if defined(CONFIG_FLASH_PAGE_LAYOUT)
116+
static void
117+
flash_native_posix_pages_layout(struct device *dev,
118+
const struct flash_pages_layout **layout,
119+
size_t *layout_size)
120+
{
121+
const struct flash_native_posix_config *config = DEV_CONFIG(dev);
122+
*layout = &config->layout;
123+
*layout_size = 1;
124+
}
125+
#endif /* CONFIG_FLASH_PAGE_LAYOUT */
126+
127+
static int flash_native_posix_init(struct device *dev)
128+
{
129+
struct flash_native_posix_data *const data = DEV_DATA(dev);
130+
const struct flash_native_posix_config *config = DEV_CONFIG(dev);
131+
132+
data->init_called = true;
133+
134+
k_sem_init(&data->mutex, 1, 1);
135+
136+
if (data->flash_path == NULL) {
137+
data->flash_path = default_flash_path;
138+
}
139+
140+
data->fd = open(data->flash_path, O_RDWR | O_CREAT, (mode_t)0600);
141+
if (data->fd == -1) {
142+
posix_print_warning("Failed to open flash device file "
143+
"%s: %s\n",
144+
data->flash_path, strerror(errno));
145+
return -EIO;
146+
}
147+
148+
if (ftruncate(data->fd, config->flash_size) == -1) {
149+
posix_print_warning("Failed to resize flash device file "
150+
"%s: %s\n",
151+
data->flash_path, strerror(errno));
152+
return -EIO;
153+
}
154+
155+
data->flash = mmap(NULL, config->flash_size,
156+
PROT_WRITE | PROT_READ, MAP_SHARED, data->fd, 0);
157+
if (data->flash == MAP_FAILED) {
158+
posix_print_warning("Failed to mmap flash device file "
159+
"%s: %s\n",
160+
data->flash_path, strerror(errno));
161+
return -EIO;
162+
}
163+
164+
LOG_INF("Device %s initialized", DEV_NAME(dev));
165+
166+
return 0;
167+
}
168+
169+
static const struct flash_driver_api flash_native_posix_driver_api = {
170+
.read = flash_native_posix_read,
171+
.write = flash_native_posix_write,
172+
.erase = flash_native_posix_erase,
173+
.write_protection = flash_native_posix_write_protection,
174+
#if defined(CONFIG_FLASH_PAGE_LAYOUT)
175+
.page_layout = flash_native_posix_pages_layout,
176+
#endif
177+
.write_block_size = 1,
178+
};
179+
180+
static const struct flash_native_posix_config flash_native_posix_config = {
181+
.flash_size = DT_FLASH_SIZE * 1024,
182+
#if defined(CONFIG_FLASH_PAGE_LAYOUT)
183+
.layout = { .pages_count = (DT_FLASH_SIZE * 1024) /
184+
(CONFIG_FLASH_NATIVE_POSIX_SECTOR_SIZE * 1024),
185+
.pages_size = CONFIG_FLASH_NATIVE_POSIX_SECTOR_SIZE * 1024
186+
},
187+
#endif
188+
};
189+
190+
static struct flash_native_posix_data flash_native_posix_data;
191+
192+
DEVICE_AND_API_INIT(flash_native_posix_0, DT_FLASH_DEV_NAME,
193+
&flash_native_posix_init, &flash_native_posix_data,
194+
&flash_native_posix_config, POST_KERNEL,
195+
CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
196+
&flash_native_posix_driver_api);
197+
198+
static void flash_native_posix_cleanup(void)
199+
{
200+
struct flash_native_posix_data *const data = &flash_native_posix_data;
201+
const struct flash_native_posix_config *config =
202+
&flash_native_posix_config;
203+
204+
if (!data->init_called) {
205+
return;
206+
}
207+
208+
if (data->flash != MAP_FAILED) {
209+
munmap(data->flash, config->flash_size);
210+
}
211+
212+
if (data->fd != -1) {
213+
close(data->fd);
214+
}
215+
}
216+
217+
void flash_native_posix_options(void)
218+
{
219+
static struct args_struct_t flash_options[] = {
220+
{ .manual = false,
221+
.is_mandatory = false,
222+
.is_switch = false,
223+
.option = "flash",
224+
.name = "path",
225+
.type = 's',
226+
.dest = (void *)&flash_native_posix_data.flash_path,
227+
.call_when_found = NULL,
228+
.descript = "Path to binary file to be used as flash" },
229+
ARG_TABLE_ENDMARKER
230+
};
231+
232+
native_add_command_line_opts(flash_options);
233+
}
234+
235+
NATIVE_TASK(flash_native_posix_options, PRE_BOOT_1, 1);
236+
NATIVE_TASK(flash_native_posix_cleanup, ON_EXIT, 1);

0 commit comments

Comments
 (0)