Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers: disk_flash: Create disk_flash driver #62527

Closed

Conversation

kica-z
Copy link
Contributor

@kica-z kica-z commented Sep 12, 2023

For our project we created a driver that emulates a flash on an underlying disk. We use this to emulate the secondary partition of mcuboot on an spi SD-Card. Since this driver could be usefull to some people we would like to upstream it.

Before that there are however some questions I have since this is the first zephyr driver I develop:

  • Is this driver a welcome addition to the codebase or is there no use case outside our project?
  • should the init_level of the driver be configurable? Currently it is APPLICATION since the ramdisk driver is initialized at APPLICATION level. If yes how should I go about that? Add it to the devicetree?
  • Can the FLASH_DISK_BUFFER_SIZE be evaluated at compile time from the underlying disk? Or is there a way to determine and allocate it during runtime without having to define a Kconfig?
  • Is there a nicer way to define the device init macro than to define it twice just because of the flash_pages?

@zephyrbot zephyrbot added area: Devicetree Binding PR modifies or adds a Device Tree binding area: Flash labels Sep 12, 2023
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @kica-z, and thank you very much for your first pull request to the Zephyr project!

A project maintainer just triggered our CI pipeline to run it against your PR and ensure it's compliant and doesn't cause any issues. You might want to take this opportunity to review the project's Contributor Expectations and make any updates to your pull request if necessary. 😊

@desowin desowin requested review from tmon-nordic and removed request for desowin September 12, 2023 14:12
@carlescufi
Copy link
Member

Hi and thanks!

Is this driver a welcome addition to the codebase or is there no use case outside our project?

I am no expert but this does sound useful to me.

should the init_level of the driver be configurable?

Yes, please create a Kconfig option for this

Can the FLASH_DISK_BUFFER_SIZE be evaluated at compile time from the underlying disk? Or is there a way to determine and allocate it during runtime without having to define a Kconfig?
Is there a nicer way to define the device init macro than to define it twice just because of the flash_pages?

I hope @de-nordic can answer that.

@de-nordic
Copy link
Collaborator

Before that there are however some questions I have since this is the first zephyr driver I develop:

* Is this driver a welcome addition to the codebase or is there no use case outside our project?

I guess many things have no use unless you show how they work.
Using SD card as a way to store MCUboot slots looks interesting although I would like to see a sample configuration for that.
That would probably by the only use now as both LittleFS and FAT FS are using Disk Access to access SD card.

* should the `init_level` of the driver be configurable? Currently it is `APPLICATION` since the `ramdisk` driver is initialized at `APPLICATION` level. If yes how should I go about that? Add it to the devicetree?

It should be configurable, but not also that SD card is something that is removable so this needs to be addressed.

* Can the `FLASH_DISK_BUFFER_SIZE` be evaluated at compile time from the underlying disk? Or is there a way to determine and allocate it during runtime without having to define a Kconfig?

Developers working on Disk Access have recently moved a lot of settings to DTS where they have become property of Disk nodes.
I would avoid any Kconfig possible and move all possible settings under DTS.
Look at previous work done for Disk Access.

* Is there a nicer way to define the device init macro than to define it twice just because of the `flash_pages`?

COND_CODE_1/0 macros.

@Laczen
Copy link
Collaborator

Laczen commented Sep 13, 2023

@kica-z, thanks for the PR this feature would indeed be highly appreciated.

One difficulty I see: the proposed PR is kind of making a partition on disk by specifying the offset and the size. But the other systems using the disk (fatfs, littlefs) are not aware that this is happening, how is this handled ?

@kica-z
Copy link
Contributor Author

kica-z commented Sep 13, 2023

@carlescufi, @de-nordic I moved the disk-sector-size as well as the init-level of the driver into the dts so that it can be adjusted for each instance individually.

@de-nordic Regarding the SD mcuboot example I can try to add one but this will take some time since for our project we use the nordic tools and the nrf fork so some adjustment is necessary.

@de-nordic What do you mean when you say keeping in mind that the sd-card is removable. Should not access to the disk-api fail as soon as the sd-card is disconnected? What would you expect from the driver in this scenario? Wait for it to reapear and reinit with the new sector size? Or just check every call if the sector buffer is sufficient?

@Laczen Currently we in the project create a separate partition on the sd-card for this and manually take care that there is no overlap between the fs and the disk_flash. It is true, that when the user defines overlapping partitions with e.g. fatfs,littlefs this will not be detected and lead to errors. Do you think there has to be a mechanism to detect this instead of leaving this to the user?

@Laczen
Copy link
Collaborator

Laczen commented Sep 13, 2023

@Laczen Currently we in the project create a separate partition on the sd-card for this and manually take care that there is no overlap between the fs and the disk_flash. It is true, that when the user defines overlapping partitions with e.g. fatfs,littlefs this will not be detected and lead to errors. Do you think there has to be a mechanism to detect this instead of leaving this to the user?

I don't see how this can be done. The sd-card size is unknown (maybe this is what @de-nordic is referring to with the removable sd-card) and there is no partitioning of sd-cards (correct me if I'm wrong).

@kica-z
Copy link
Contributor Author

kica-z commented Sep 13, 2023

@Laczen we do actually partition our sd-card. In our project fatfs uses the D: partition and the disk_flash is writing into the OEM partition.
image

@Laczen
Copy link
Collaborator

Laczen commented Sep 13, 2023

@Laczen we do actually partition our sd-card. In our project fatfs uses the D: partition and the disk_flash is writing into the OEM partition. image

What does zephyr report about this disk ? Can it detect the D partition and the OEM partition ? How is the fatfs limited to the D: partition ?

@kica-z
Copy link
Contributor Author

kica-z commented Sep 14, 2023

@Laczen The disk-api reports the full size of the sd-card no matter what partitions are defined on the card (calculated by sector_count * sector_size). Fatfs however detects the filesystem in the first partition and reports only the size of that partition as its size (f_blocks * f_frsize).

So at least in this constellation (fs partition first -> oem after) it seems to work as intended. The disk_flash driver of course still needs to be tuned to write into the oem partition as there is no autodetection or similar implemented here.

@Laczen
Copy link
Collaborator

Laczen commented Sep 14, 2023

@kica-z it seems fragile to rely on the existence of a fatfs partition to allow this to work. At first glance this wouldn't be supported when littlefs is used on the disk.

@kica-z
Copy link
Contributor Author

kica-z commented Sep 14, 2023

@Laczen I am not quite sure I understood your comment correctly so correct me if i misinterpreted it:

I don't think the driver is responsible for supporting the user in configuring his block device.
Both fatfs and littlefs have mechanisms that allow them to not use the entire space on a disk. So if a user wants to use a FS in addition to this driver that is fine as long as it does not read/write on the same diskspace as the disk_flash. Even read/write on the same diskspace would be fine from disk_flash point of view but the FS will likely get corrupted.

So in conclusion the driver is not relying on a fatfs partition to be present. The user simply has to configure his setup according to his needs which might then need a fatfs or littlefs that is not using the entire diskspace of a disk.

I however agree that this might be a topic for documentation in order to support the user with using this driver in parallel to a fs.

@Laczen
Copy link
Collaborator

Laczen commented Sep 14, 2023

I don't think the driver is responsible for supporting the user in configuring his block device. Both fatfs and littlefs have mechanisms that allow them to not use the entire space on a disk. So if a user wants to use a FS in addition to this driver that is fine as long as it does not read/write on the same diskspace as the disk_flash. Even read/write on the same diskspace would be fine from disk_flash point of view but the FS will likely get corrupted.

I don't think this is true for littlefs, it always uses the entire disk. I also doubt that it is possible to create a fatfs partition in zephyr that uses only part of the disk, so if a mkfs is done in zephyr this will also consume the whole disk.

@kica-z
Copy link
Contributor Author

kica-z commented Sep 14, 2023

@Laczen I stand corrected littlefs really seems to not support partially using a disk. I misinterpreted a documentation entry. I don't know mkfs of zephyr well enough to make a statement regarding the possibility of not using the whole disk. It is quite possible that this is not possible.

However you could circumvent this problem by defining two disk_flash devices and running littlefs/fatfs on one of them as both FS also support the flash_api. This way there would be no overlap. I have however not tested this yet.

But as already mentioned I think the support of a filesystem on the same disk is not a requirement for this driver to be usefull. It would definitely be a nice to have though.

@Laczen
Copy link
Collaborator

Laczen commented Sep 14, 2023

However you could circumvent this problem by defining two disk_flash devices and running littlefs/fatfs on one of them as both FS also support the flash_api. This way there would be no overlap. I have however not tested this yet.

This would indeed be a solution to avoid the problem. But I don't think it is possible at the moment to "split" or partition a disk.

@danieldegrasse are there any plans to allow splitting or partitioning a disk (e.g. some fixed size raw zephyr-disk, and then a variable sized disk for a filesystem) ?

But as already mentioned I think the support of a filesystem on the same disk is not a requirement for this driver to be usefull. It would definitely be a nice to have though.

I agree it would be nice to have this,

@danieldegrasse
Copy link
Collaborator

@danieldegrasse are there any plans to allow splitting or partitioning a disk (e.g. some fixed size raw zephyr-disk, and then a variable sized disk for a filesystem) ?

No plans currently from me. I expect this could be achieved by defining an emulated disk driver that simply reported a different sector count than the underlying disk device it was exposing. Multiple disk drivers like this could be combined to "parition" a disk with the current API

As far as the PR itself, this looks like a useful addition. Although the only use case I'm aware of is MCUBoot, there are still likely cases where users want to use MCUBoot as the bootloader but store boot images on a SD or eMMC device

@kica-z
Copy link
Contributor Author

kica-z commented Sep 15, 2023

No plans currently from me. I expect this could be achieved by defining an emulated disk driver that simply reported a different sector count than the underlying disk device it was exposing. Multiple disk drivers like this could be combined to "parition" a disk with the current API

I thought about this too and think it could be a useful addition. Maybe even add a devicetree entry partitions for disk devices like it currently is available for flash via fixed-partitions. However I think this should be discussed in a separate issue or PR.

@kica-z kica-z force-pushed the feature/disk-flash-new branch 4 times, most recently from f7228a7 to 9abd7d4 Compare September 19, 2023 15:17
@jfischer-no jfischer-no self-requested a review September 19, 2023 19:59
@kica-z
Copy link
Contributor Author

kica-z commented Nov 14, 2023

@jfischer-no @carlescufi What is the status here? Is there something I am missing before a new review can be done?

# Copyright (c) 2023 Endress+Hauser AG
# SPDX-License-Identifier: Apache-2.0

config FLASH_DRIVER_DISK
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are few inconsistencies, compatibility is "zephyr,disk-flash", let's align everything to it, Kconfig.disk -> Kconfig.disk_flash, flash_disk.c -> disk_flash.c, CONFIG_FLASH_DRIVER_DISK -> CONFIG_DISK_FLASH_DRIVER or CONFIG_DISK_FLASH ....

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed for better consistency

Comment on lines 18 to 28
struct flash_disk_dev_data {
#if defined(CONFIG_MULTITHREADING)
struct k_sem sem;
#endif
char *const sector_buf;
uint16_t const sector_buf_size;
uint32_t disk_total_sector_cnt;
uint32_t disk_sector_size;
};

struct flash_disk_dev_config {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

struct disk_flash_data, struct disk_flash_config, see comment about inconsistent naming, it is obvious what these are, no need to have dev in name.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adjusted

const struct flash_disk_dev_config *cfg;
uint32_t write_cursor = 0;

LOG_DBG("%s called", __func__);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove func, use https://docs.zephyrproject.org/latest/kconfig.html#CONFIG_LOG_FUNC_NAME_PREFIX_DBG, do not use LOG_DBG for tracing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

{
int ret = 0;
char *dst_buf = (char *)dst;
struct flash_disk_dev_data *data;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Proper drivers would do:

const struct disk_flash_config *cfg = dev->config;
struct disk_flash_data *data = dev->data;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved the pointer assignment as mentioned here.

static int flash_disk_read(const struct device *dev, off_t offset, void *dst, size_t len)
{
int ret = 0;
char *dst_buf = (char *)dst;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uint8_t *dst_buf = dst;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adjusted

memcpy(&dst_buf[write_cursor], &data->sector_buf[read_padding], len_write);
write_cursor += len_write;
}
release_device:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

	}

release_device:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adjusted

Comment on lines 1 to 51
/*
* Copyright (c) 2023 Endress+Hauser AG
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/flash.h>
#include <zephyr/logging/log.h>

#if DT_HAS_COMPAT_STATUS_OKAY(zephyr_disk_flash)
#define FLASH_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(zephyr_disk_flash)
#else
#error Unsupported flash driver
#define FLASH_NODE DT_INVALID_NODE
#endif

LOG_MODULE_REGISTER(main, CONFIG_LOG_DEFAULT_LEVEL);

int main(void)
{
int res = 0;
const struct device *const dev = DEVICE_DT_GET(FLASH_NODE);

if (!device_is_ready(dev)) {
LOG_ERR("%s: device not ready\n", dev->name);
return 0;
}

char testWrite[] = "This was written to flash_disk.";
char testRead[sizeof(testWrite)];

res = flash_write(dev, (off_t)20, testWrite, sizeof(testWrite));
if (res != 0) {
LOG_ERR("Flash write failed");
}

res = flash_read(dev, (off_t)20, testRead, sizeof(testRead));
if (res != 0) {
LOG_ERR("Flash read failed");
}

if (strcmp(testWrite, testRead) != 0) {
LOG_ERR("Flash read return wrong data: \"%s\" != \"%s\"", testWrite, testRead);
} else {
LOG_INF("Read/Write test successful");
}

return 0;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no benefit to adding a specific sample for a driver that uses a generic API. This should work fine with e.g. samples/drivers/flash_shell (just move app.overlay to samples/drivers/flash_shell/disk_flash.overlay).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the sample and added overlays to work with the flash_shell sample.
-> Can be build by running: west build -b qemu_x86 samples/drivers/flash_shell/ -DDTC_OVERLAY_FILE=disk_flash.overlay -DOVERLAY_CONFIG=disk_flash.conf

CONFIG_MINIMAL_LIBC=y

# Enable flash on disk
CONFIG_FLASH_DRIVER_DISK=y
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should not be explicitly enabled because of:


	default y
	depends on DT_HAS_ZEPHYR_DISK_FLASH_ENABLED

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

/ {
ramdisk0 {
compatible = "zephyr,ram-disk";
disk-name = "DISK1";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

disk-name = "DISK0"; or disk-name = "ramdisk"; ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed

Comment on lines +18 to +37
disk-sector-size:
type: int
description: the sector size in byte of the underlying disk to be used
required: true
disk-offset:
type: int
description: >
offset on the disk in bytes. If the offset is 10 the 10th byte will
be the first one used.
default: 0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The information is already there, there must not be an other property to describe the same, please take a look at DT_INST_PROP_BY_PHANDLE, ping me if you need help with that.

@kica-z
Copy link
Contributor Author

kica-z commented Nov 20, 2023

@jfischer-no Except for the point you mentioned with the offset everything is adjusted now. With the offset I would appreciate some support since there seems to be a bit of a misunderstanding.

@kica-z kica-z force-pushed the feature/disk-flash-new branch 2 times, most recently from 83966c7 to 3f0c0ed Compare November 21, 2023 08:46
Comment on lines +133 to +131
uint32_t write_cursor = cfg->disk_offset + offset + read_cursor;
uint32_t write_sector = write_cursor / data->disk_sector_size;
uint32_t write_padding = write_cursor % data->disk_sector_size;
uint32_t len_write = (len - read_cursor);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think it is very efficient to keep recalculating these in loop.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@de-nordic
I agree that this is not very efficient but I don't see a way around it since the driver allows arbitrary write/read sizes and does not need to be sector aligned with the disk.

I understood you believe, that read/write/erase granularity must be equal to the underlying disk device. The idea of this flash driver is to offer a read/write/erase granularity of a single byte on top of a disk with arbitrary sector sizes. So operations typically:
-read sector,
-update sector,
-write sector,
-loop

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is bad. This means that half of sector may belong to something else.
And another thing is that SD card is block device. Read/write and emulated erase happens in blocks.
If you modify single byte what will happen is that entire sector needs to be re-written by a controller.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But unless done this way, how would you simulate a flash with potentially different properties then underlying device?

Would you prefer, that flash_disk inherits properties from underlying device? If so, it would probably no longer be suitable for our use-case.
I see the following possibilities:

  1. be at maximum permissive granularity (1 byte, current proposal)
  2. be user configurable (with Kconfig?)
  3. same as underlying device (severely limiting the usefulness of it to emulate a device with different properties on top of another)

Of course with 1. it is expected, that caller calls with big junks also. With 3. it is not possible to use as secondary partition for mcuboot if underlying device has different properties to main flash. Which would nullify the main benefit of the flash_disk module.

Or am I missing something? Can primary and secondary partition for mcuboot have different properties?
If yes, then of course, the story is entirely different.

Thanks for the quick responses and instructing reviews.

Copy link
Contributor

@clamattia clamattia Nov 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or did I completely miss your point and you suggestions is just to improve simply the code to:

  • handle initial (potentially misaligned) sector
  • handle most sectors with single call to disk_access
  • handle final (potentially misaligned) sector

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for elaborating your concerns, I think, that I understand better now. Did I understand your concerns correclty, that:

  1. The trailer containing meta-information about the slot is written at the end of each slot. So there is a trailer at the end of the secondary slot on the flash_disk. Did I understand correctly, that this would mean, that whereas on a flash the trailer is erased once and then progressively written the flash-disk would need to read-update-write the sector containing the trailer with each status update which concerns you because of too much wear on disks without wear-leveling?
  2. You are worried, that the write of a sector is not an atomic operation, such that it might end up being half-written for example in case of power-loss? Leading to possible damage to the system.

There is another issue that there is very small chance that you can break the status update when record is added, but when you break it while write block happens, what will happen is that there will not longer be record of any swap happening and, at the same time, you will have two damaged slots (partially swapped).

Are you refering to the fact, that swapping might fail when using swap-using-move on an image that is too big (100% of available space) because it can not move down the primary imgage block-wise when there is no free block? Whereas this can not happen when using swap-using-scratch? Or is there another reason for recommending swap using scratch?

Thanks

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both with swap-using-move and swap-using-scratch the result of a block move is written to flash. When using a disk and the write of the last sector fails you could loose all information about the process (all information is on one disk sector), while on flash only the last block move information might be incorrect. If all information is lost there is no way to continue the swap and you are left with an unrecoverable system.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood.
So it would not matter which strategy here?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the strategy does not matter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@de-nordic @Laczen

Shouldn't the danger of sector write fail be lowered since when not written entirely the sd-card should still contain a partially correct sector? Or how is the status of the swap tracked? By settings bytes to 0?

Also I do not currently see any mitigation for the two problems brought up in this thread. Neither for the problem with the high disk usage due to sector overwrites nor for the problem with partial writes. Do you see any mitigation possibilites here or what would/should be the way forward?

data->disk_sector_size);
}

disk_size = data->disk_sector_size * data->disk_total_sector_cnt;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

size_t may not be enough to hold the value. On 32 bit platform that is up to 4G. Is it possible that larger devices would be used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. There is absolutely a possibility that large disks could be used since this driver supports partitioning. I adjusted this.

Comment on lines +206 to +199
memset(&data->sector_buf[write_padding],
cfg->flash_parameters.erase_value,
len_write);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could do that once, before entering the loop.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the erase supports arbitrary size and does not need to be aligned with the sector of the disk partial sectors need to be erased. Therefore I don't currently see a possibility to do this outside the loop.

Comment on lines +187 to +181
uint32_t write_cursor = cfg->disk_offset + offset + read_cursor;
uint32_t write_sector = write_cursor / data->disk_sector_size;
uint32_t write_padding = write_cursor % data->disk_sector_size;
uint32_t len_write = (size - read_cursor);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that both cursors will be moved by sector size or multiple of that? Looks like too much arithmetic for adding sector size.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessarily moved by sector size since the driver is not dependent on the underlying disk sector size partial sectors may be written or read. As such I think that much arithmetic is needed.

.flash_size = DT_INST_PROP(index, size), \
.flash_parameters = \
{ \
.write_block_size = 1, \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think this is good idea. If you try to loop writing data with such block size, what would happen is that you would probably get one sector erased and rewritten by number of bytes in sector. Or SD controller, if it is something super smart, will do number of sector reallocations equal to sector size in bytes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not completely understand this comment but I had both write_block size and erase_size as DT property before but was told that this should not be necessary:

Why would this need to be configurable? The underlying disk controller should always support 1 byte block writes

As I mentioned before this driver aims to be as independent from the underlying disk block size as possible and does currently support arbitrary read/write/erase sizes.

(.fpl = \
{ \
.pages_count = DT_INST_PROP(index, size), \
.pages_size = 1 \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Erase at least by sector size.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to make this driver dependent on the disk sector size? This driver currently supports arbitrary write/read/erase sizes independent from the underlying disk.

Comment on lines 89 to 92
if (read_sector < 0 || read_sector >= data->disk_total_sector_cnt) {
ret = -EINVAL;
goto release_device;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the range be tested before entering the loop?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. This check actually is not even needed anymore. With the check_boundary function we check that the read/write is within the defined flash partition and in disk_flash_init we check that the partition is within the underlying disk.

Comment on lines 138 to 142
if (write_sector < 0 || write_sector >= data->disk_total_sector_cnt) {
LOG_ERR("Sector out of bounds");
ret = -EINVAL;
goto release_device;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the range be tested before entering the loop?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. This check actually is not even needed anymore. With the check_boundary function we check that the read/write is within the defined flash partition and in disk_flash_init we check that the partition is within the underlying disk.

@kica-z
Copy link
Contributor Author

kica-z commented Nov 24, 2023

Added page-size as DTS property again since it is needed for mcuboot to be able to match the primary flash page size. Also defined the size in bits again since nrf-partition-manager gets confused otherwise (also done like this in other flash drivers).

@kica-z kica-z force-pushed the feature/disk-flash-new branch 2 times, most recently from 0d4e9ed to 8c9a868 Compare December 6, 2023 12:09
@jfischer-no
Copy link
Collaborator

Added page-size as DTS property again since it is needed for mcuboot to be able to match the primary flash page size. Also defined the size in bits again since nrf-partition-manager gets confused otherwise (also done like this in other flash drivers).

Neither MCUBoot nor nrf-partition-manager (?) are Zephyr projects; there should be nothing specific to them in a Zephyr RTOS driver.

@kica-z
Copy link
Contributor Author

kica-z commented Dec 7, 2023

Added page-size as DTS property again since it is needed for mcuboot to be able to match the primary flash page size. Also defined the size in bits again since nrf-partition-manager gets confused otherwise (also done like this in other flash drivers).

Neither MCUBoot nor nrf-partition-manager (?) are Zephyr projects; there should be nothing specific to them in a Zephyr RTOS driver.

@jfischer-no You are correct of course but these softwares showed the errors/shortcomings the driver still was having. Defining disk size in bits is done in other flash drivers as well so I merely adjusted the driver to better fit in with those drivers. Also being able to define the page size is a valuable additon for a flash-emulator no matter if used with mcuboot or not.

Create a driver that emulates a flash storage on the disk api.
This enables e.g. using an spi SD-Card as secondary partition
for mcuboot.

Signed-off-by: Carlo Kirchmeier <[email protected]>
Copy link

This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.

@github-actions github-actions bot added the Stale label Feb 13, 2024
@github-actions github-actions bot closed this Feb 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Devicetree Binding PR modifies or adds a Device Tree binding area: Flash area: Samples Samples Stale
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants