Skip to content

Commit

Permalink
flash_partitions: a flash_map alternative
Browse files Browse the repository at this point in the history
Working with partitions on a flash device has been done using the
flash_map subsystem. The flash_map subsystem has been limiting
(e.g. #52395) and does not support support for flash devices that
do not need an erase (non flash devices that are supported as if they
are flash).

The PR proposes an alternative for flash_map that supports classic flash
devices, "no-erase" flash devices. Partitions can be read-only, and it
is possible to provide an "override" erase-block-size.

The support for "no-erase" flash devices is achieved by the definition
of a "zephyr,flash-no-erase" compatible that is added to the flash
device.

Signed-off-by: Laczen JMS <laczenjms@gmail.com>
  • Loading branch information
Laczen committed Apr 5, 2024
1 parent c97a813 commit 509b9e1
Show file tree
Hide file tree
Showing 8 changed files with 517 additions and 0 deletions.
6 changes: 6 additions & 0 deletions dts/bindings/misc/zephyr,flash-no-erase.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copyright (c) 2024 Laczen
# SPDX-License-Identifier: Apache-2.0

description: Compatible describing that a flash device has no erase.

compatible: "zephyr,flash-no-erase"
99 changes: 99 additions & 0 deletions dts/bindings/misc/zephyr,flash-partitions.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
description: |
This binding is used to describe fixed partitions of a flash memory.
Here is an example:
&flash0 {
partitions {
compatible = "zephyr,flash-partitions";
#address-cells = <1>;
#size-cells = <1>;
boot_partition: partition@0 {
label = "mcuboot";
reg = <0x00000000 0x0000C000>;
};
slot0_partition: partition@c000 {
label = "image-0";
reg = <0x0000C000 0x00076000>;
};
slot1_partition: partition@82000 {
label = "image-1";
reg = <0x00082000 0x00076000>;
};
/*
* The flash starting at 0x000f8000 and ending at
* 0x000fffff is reserved for use by the application.
*/
/*
* Storage partition will be used by FCB/LittleFS/NVS
* if enabled.
*/
storage_partition: partition@f8000 {
label = "storage";
reg = <0x000f8000 0x00008000>;
};
};
};
Note that the usual name for this node is 'partitions'.
The zephyr,flash-partitions node should be a child of the flash
memory node. Note also that the flash memory node is usually
different from the node representing the flash controller
IP block.
Above, slot0_partition's register address 0xc000 means that
the partition begins at that offset from the parent flash
memory flash0's base address. That is, partition addresses
are relative; physical addresses must be calculated by adding
the start address of flash0 in memory to each partition's
reg address.
compatible: "zephyr,flash-partitions"

properties:
"#address-cells":
type: int
description: |
Number of cells required to represent a child node's
reg property address. This must be large enough to
represent the start offset of each partition.
"#size-cells":
type: int
description: |
Number of cells required to represent a child node's
reg property address. This must be large enough to
represent the size of each partition in bytes.
child-binding:
description: |
Each child node of the zephyr,flash-partitions node represents
an individual flash partition. These should usually
look like this:
partition_nodelabel: partition@START_OFFSET {
label = "human-readable-name";
reg = <0xSTART_OFFSET 0xSIZE>;
};
properties:
label:
type: string
description: |
Human readable string describing the flash partition.
read-only:
type: boolean
description: set this property if the partition is read-only
erase-block-size:
type: int
description: override value for the flash node erase-block-size.
reg:
type: array
description: |
This should be in the format <OFFSET SIZE>, where OFFSET
is the offset of the flash partition relative to the base
address of the parent memory, and SIZE is the size of
the partition in bytes.
required: true
174 changes: 174 additions & 0 deletions include/zephyr/storage/flash_partitions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/*
* Copyright (c) 2024 Laczen
*
* SPDX-License-Identifier: Apache-2.0
*/

/**
* @file
* @brief Public API for flash partitions
*/

#ifndef ZEPHYR_INCLUDE_FLASH_PARTITIONS_H_
#define ZEPHYR_INCLUDE_FLASH_PARTITIONS_H_

/**
* @brief Abstraction over flash memory and its partitions
*
* @defgroup flash_partitions_api flash_partitions interface
* @{
*/

/*
* This API makes it possible to operate on flash partitions easily and
* effectively.
*/

#include <errno.h>
#include <sys/types.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/flash.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
* The flash_partitions subsystem provide an abstraction layer between flash
* memory specific drivers and higher-level applications for flash memory
* partitions. On flash partitions the following routines for operation are
* provided: open, read, write, erase, clear and close.
*
*/

/**
* @brief Retrieve a pointer to the flash partition info struct.
*
* A flash partition with nodelabel "nodelabel" is retrieved as:
* const struct flash_partition *fp = FLASH_PARTITION_GET(nodelabel)
*
* @param nodelabel of the flash partition.
*/
#define FLASH_PARTITION_GET(nodelabel) \
&UTIL_CAT(flash_partition_, DT_NODELABEL(nodelabel))

/**
* @brief flash_partition represents a flash partition.
*/
struct flash_partition {
/** flash device */
const struct device *fldev;
/** flash partition size */
const size_t size;
/** flash partition offset on flash device */
const size_t offset;
/** flash partition erase-block-size */
const size_t erase_block_size;
/** flash partition routines */
int (*const open)(const struct flash_partition *partition);
int (*const read)(const struct flash_partition *partition, size_t start,
void *data, size_t len);
int (*const write)(const struct flash_partition *partition, size_t start,
const void *data, size_t len);
int (*const erase)(const struct flash_partition *partition, size_t start,
size_t len);
int (*const close)(const struct flash_partition *partition);
};

/**
* @brief Get the size in byte of a flash partition.
*
* @param[in] partition flash partition
* @return the size.
*/
size_t flash_partition_get_size(const struct flash_partition *partition);

/**
* @brief Get the erase-block-size in byte of a flash partition.
*
* @param[in] partition flash partition
* @return the size.
*/
size_t flash_partition_get_ebs(const struct flash_partition *partition);

/**
* @brief Open a flash partition.
*
* @param[in] partition flash partition
*
* @return 0 on success, negative errno code on fail.
*/
int flash_partition_open(const struct flash_partition *partition);

/**
* @brief Read data from flash partition. Read boundaries are verified before
* read request is executed.
*
*
* @param[in] partition flash partition
* @param[in] start point relative from beginning of flash partition
* @param[out] data Buffer to store read data
* @param[in] len Size to read
*
* @return 0 on success, negative errno code on fail.
*/
int flash_partition_read(const struct flash_partition *partition, size_t start,
void *data, size_t len);

/**
* @brief Write data to flash partition. Write boundaries are verified before
* write request is executed.
*
* @param[in] partition flash partition
* @param[in] start point relative from beginning of flash partition
* @param[out] data Buffer with data to be written
* @param[in] len Size to read
*
* @return 0 on success, negative errno code on fail.
*/
int flash_partition_write(const struct flash_partition *partition, size_t start,
const void *data, size_t len);

/**
* @brief Erase range on flash partition. Erase boundaries are verified before
* erase is executed.
*
* @param[in] partition flash partition
* @param[in] start point relative from beginning of flash partition
* @param[in] len Size to erase
*
* @return 0 on success, negative errno code on fail.
*/
int flash_partition_erase(const struct flash_partition *partition, size_t start,
size_t len);

/**
* @brief Close a flash partition.
*
* @param[in] partition flash partition
*
* @return 0 on success, negative errno code on fail.
*/
int flash_partition_close(const struct flash_partition *partition);

/** @cond INTERNAL_HIDDEN */

#define FLASH_PARTITION_DECLARE(n) \
extern const struct flash_partition flash_partition_##n;

#define FLASH_PARTITIONS_DECLARE(inst) \
DT_FOREACH_CHILD_STATUS_OKAY(inst, FLASH_PARTITION_DECLARE)

DT_FOREACH_STATUS_OKAY(zephyr_flash_partitions, FLASH_PARTITIONS_DECLARE)
/** @endcond */

#ifdef __cplusplus
}
#endif

/**
* @}
*/

#endif /* ZEPHYR_INCLUDE_FLASH_PARTITIONS_H_ */
1 change: 1 addition & 0 deletions subsys/storage/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: Apache-2.0

add_subdirectory_ifdef(CONFIG_FLASH_MAP flash_map)
add_subdirectory_ifdef(CONFIG_FLASH_PARTITIONS flash_partitions)
add_subdirectory_ifdef(CONFIG_STREAM_FLASH stream)
1 change: 1 addition & 0 deletions subsys/storage/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
menu "Storage"

source "subsys/storage/flash_map/Kconfig"
source "subsys/storage/flash_partitions/Kconfig"
source "subsys/storage/stream/Kconfig"

endmenu
4 changes: 4 additions & 0 deletions subsys/storage/flash_partitions/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# SPDX-License-Identifier: Apache-2.0

zephyr_library()
zephyr_library_sources(flash_partitions.c)
26 changes: 26 additions & 0 deletions subsys/storage/flash_partitions/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright (c) 2024, Laczen
# SPDX-License-Identifier: Apache-2.0

menuconfig FLASH_PARTITIONS
bool "flash partitions support"
default y if DT_HAS_ZEPHYR_FLASH_PARTITIONS_ENABLED
select FLASH
help
Enables support for the flash partitions system, which enables using
unified routines to work with partitions defined on flash devices.

if FLASH_PARTITIONS

config FLASH_PARTITIONS_RUNTIME_VERIFY
bool "runtime verification of erase-block-size"
default n
select FLASH_PAGE_LAYOUT
help
Enable runtime verification that erase-block-size is a multiple of the
flash erase block size.

module = FLASH_PARTITIONS
module-str = flash_partitions
source "subsys/logging/Kconfig.template.log_config"

endif #FLASH_PARTITIONS
Loading

0 comments on commit 509b9e1

Please sign in to comment.