dt: Make zephyr,memory-attr a capabilities bitmask
This is the final step in making the `zephyr,memory-attr` property
actually useful.
The problem with the current implementation is that `zephyr,memory-attr`
is an enum type, this is making very difficult to use that to actually
describe the memory capabilities. The solution proposed in this PR is to
use the `zephyr,memory-attr` property as an OR-ed bitmask of memory
attributes.
With the change proposed in this PR it is possible in the DeviceTree to
mark the memory regions with a bitmask of attributes by using the
`zephyr,memory-attr` property. This property and the related memory
region can then be retrieved at run-time by leveraging a provided helper
library or the usual DT helpers.
The set of general attributes that can be specified in the property are
defined and explained in
`include/zephyr/dt-bindings/memory-attr/memory-attr.h` (the list can be
extended when needed).
For example, to mark a memory region in the DeviceTree as volatile,
non-cacheable, out-of-order:
mem: memory@10000000 {
compatible = "mmio-sram";
reg = <0x10000000 0x1000>;
zephyr,memory-attr = <( DT_MEM_VOLATILE |
DT_MEM_NON_CACHEABLE |
DT_MEM_OOO )>;
};
The `zephyr,memory-attr` property can also be used to set
architecture-specific custom attributes that can be interpreted at run
time. This is leveraged, among other things, to create MPU regions out
of DeviceTree defined memory regions on ARM, for example:
mem: memory@10000000 {
compatible = "mmio-sram";
reg = <0x10000000 0x1000>;
zephyr,memory-region = "NOCACHE_REGION";
zephyr,memory-attr = <( DT_ARM_MPU(ATTR_MPU_RAM_NOCACHE) )>;
};
See `include/zephyr/dt-bindings/memory-attr/memory-attr-mpu.h` to see
how an architecture can define its own special memory attributes (in
this case ARM MPU).
The property can also be used to set custom software-specific
attributes. For example we can think of marking a memory region as
available to be used for memory allocation (not yet implemented):
mem: memory@10000000 {
compatible = "mmio-sram";
reg = <0x10000000 0x1000>;
zephyr,memory-attr = <( DT_MEM_NON_CACHEABLE |
DT_MEM_SW_ALLOCATABLE )>;
};
Or maybe we can leverage the property to specify some alignment
requirements for the region:
mem: memory@10000000 {
compatible = "mmio-sram";
reg = <0x10000000 0x1000>;
zephyr,memory-attr = <( DT_MEM_CACHEABLE |
DT_MEM_SW_ALIGN(32) )>;
};
The conventional and recommended way to deal and manage with memory
regions marked with attributes is by using the provided `mem-attr`
helper library by enabling `CONFIG_MEM_ATTR` (or by using the usual DT
helpers).
When this option is enabled the list of memory regions and their
attributes are compiled in a user-accessible array and a set of
functions is made available that can be used to query, probe and act on
regions and attributes, see `include/zephyr/mem_mgmt/mem_attr.h`
Note that the `zephyr,memory-attr` property is only a descriptive
property of the capabilities of the associated memory region, but it
does not result in any actual setting for the memory to be set. The
user, code or subsystem willing to use this information to do some work
(for example creating an MPU region out of the property) must use either
the provided `mem-attr` library or the usual DeviceTree helpers to
perform the required work / setting.
Signed-off-by: Carlo Caione <ccaione@baylibre.com>
2023-08-16 18:48:26 +08:00
|
|
|
.. _mem_mgmt_api:
|
|
|
|
|
|
|
|
Memory Attributes
|
|
|
|
#################
|
|
|
|
|
|
|
|
It is possible in the devicetree to mark the memory regions with attributes by
|
|
|
|
using the ``zephyr,memory-attr`` property. This property and the related memory
|
|
|
|
region can then be retrieved at run-time by leveraging a provided helper
|
|
|
|
library.
|
|
|
|
|
|
|
|
The set of general attributes that can be specified in the property are defined
|
|
|
|
and explained in :zephyr_file:`include/zephyr/dt-bindings/memory-attr/memory-attr.h`.
|
|
|
|
|
|
|
|
For example, to mark a memory region in the devicetree as non-volatile, cacheable,
|
|
|
|
out-of-order:
|
|
|
|
|
|
|
|
.. code-block:: devicetree
|
|
|
|
|
|
|
|
mem: memory@10000000 {
|
|
|
|
compatible = "mmio-sram";
|
|
|
|
reg = <0x10000000 0x1000>;
|
|
|
|
zephyr,memory-attr = <( DT_MEM_NON_VOLATILE | DT_MEM_CACHEABLE | DT_MEM_OOO )>;
|
|
|
|
};
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
The ``zephyr,memory-attr`` usage does not result in any memory region
|
|
|
|
actually created. When it is needed to create an actual section out of the
|
|
|
|
devicetree defined memory region, it is possible to use the compatible
|
|
|
|
:dtcompatible:`zephyr,memory-region` that will result (only when supported
|
|
|
|
by the architecture) in a new linker section and region.
|
|
|
|
|
|
|
|
The ``zephyr,memory-attr`` property can also be used to set
|
|
|
|
architecture-specific and software-specific custom attributes that can be
|
|
|
|
interpreted at run time. This is leveraged, among other things, to create MPU
|
|
|
|
regions out of devicetree defined memory regions, for example:
|
|
|
|
|
|
|
|
.. code-block:: devicetree
|
|
|
|
|
|
|
|
mem: memory@10000000 {
|
|
|
|
compatible = "mmio-sram";
|
|
|
|
reg = <0x10000000 0x1000>;
|
|
|
|
zephyr,memory-region = "NOCACHE_REGION";
|
|
|
|
zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>;
|
|
|
|
};
|
|
|
|
|
|
|
|
See :zephyr_file:`include/zephyr/dt-bindings/memory-attr/memory-attr-arm.h` and
|
|
|
|
:ref:`arm_cortex_m_developer_guide` for more details about MPU usage.
|
|
|
|
|
|
|
|
The conventional and recommended way to deal and manage with memory regions
|
|
|
|
marked with attributes is by using the provided ``mem-attr`` helper library by
|
|
|
|
enabling :kconfig:option:`CONFIG_MEM_ATTR`. When this option is enabled the
|
|
|
|
list of memory regions and their attributes are compiled in a user-accessible
|
|
|
|
array and a set of functions is made available that can be used to query, probe
|
|
|
|
and act on regions and attributes (see next section for more details).
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
The ``zephyr,memory-attr`` property is only a descriptive property of the
|
|
|
|
capabilities of the associated memory region, but it does not result in any
|
|
|
|
actual setting for the memory to be set. The user, code or subsystem willing
|
|
|
|
to use this information to do some work (for example creating an MPU region
|
|
|
|
out of the property) must use either the provided ``mem-attr`` library or
|
|
|
|
the usual devicetree helpers to perform the required work / setting.
|
|
|
|
|
|
|
|
A test for the ``mem-attr`` library and its usage is provided in
|
|
|
|
``tests/subsys/mem_mgmt/mem_attr/``.
|
|
|
|
|
2024-09-11 01:51:57 +08:00
|
|
|
Migration guide from ``zephyr,memory-region-mpu``
|
|
|
|
*************************************************
|
dt: Make zephyr,memory-attr a capabilities bitmask
This is the final step in making the `zephyr,memory-attr` property
actually useful.
The problem with the current implementation is that `zephyr,memory-attr`
is an enum type, this is making very difficult to use that to actually
describe the memory capabilities. The solution proposed in this PR is to
use the `zephyr,memory-attr` property as an OR-ed bitmask of memory
attributes.
With the change proposed in this PR it is possible in the DeviceTree to
mark the memory regions with a bitmask of attributes by using the
`zephyr,memory-attr` property. This property and the related memory
region can then be retrieved at run-time by leveraging a provided helper
library or the usual DT helpers.
The set of general attributes that can be specified in the property are
defined and explained in
`include/zephyr/dt-bindings/memory-attr/memory-attr.h` (the list can be
extended when needed).
For example, to mark a memory region in the DeviceTree as volatile,
non-cacheable, out-of-order:
mem: memory@10000000 {
compatible = "mmio-sram";
reg = <0x10000000 0x1000>;
zephyr,memory-attr = <( DT_MEM_VOLATILE |
DT_MEM_NON_CACHEABLE |
DT_MEM_OOO )>;
};
The `zephyr,memory-attr` property can also be used to set
architecture-specific custom attributes that can be interpreted at run
time. This is leveraged, among other things, to create MPU regions out
of DeviceTree defined memory regions on ARM, for example:
mem: memory@10000000 {
compatible = "mmio-sram";
reg = <0x10000000 0x1000>;
zephyr,memory-region = "NOCACHE_REGION";
zephyr,memory-attr = <( DT_ARM_MPU(ATTR_MPU_RAM_NOCACHE) )>;
};
See `include/zephyr/dt-bindings/memory-attr/memory-attr-mpu.h` to see
how an architecture can define its own special memory attributes (in
this case ARM MPU).
The property can also be used to set custom software-specific
attributes. For example we can think of marking a memory region as
available to be used for memory allocation (not yet implemented):
mem: memory@10000000 {
compatible = "mmio-sram";
reg = <0x10000000 0x1000>;
zephyr,memory-attr = <( DT_MEM_NON_CACHEABLE |
DT_MEM_SW_ALLOCATABLE )>;
};
Or maybe we can leverage the property to specify some alignment
requirements for the region:
mem: memory@10000000 {
compatible = "mmio-sram";
reg = <0x10000000 0x1000>;
zephyr,memory-attr = <( DT_MEM_CACHEABLE |
DT_MEM_SW_ALIGN(32) )>;
};
The conventional and recommended way to deal and manage with memory
regions marked with attributes is by using the provided `mem-attr`
helper library by enabling `CONFIG_MEM_ATTR` (or by using the usual DT
helpers).
When this option is enabled the list of memory regions and their
attributes are compiled in a user-accessible array and a set of
functions is made available that can be used to query, probe and act on
regions and attributes, see `include/zephyr/mem_mgmt/mem_attr.h`
Note that the `zephyr,memory-attr` property is only a descriptive
property of the capabilities of the associated memory region, but it
does not result in any actual setting for the memory to be set. The
user, code or subsystem willing to use this information to do some work
(for example creating an MPU region out of the property) must use either
the provided `mem-attr` library or the usual DeviceTree helpers to
perform the required work / setting.
Signed-off-by: Carlo Caione <ccaione@baylibre.com>
2023-08-16 18:48:26 +08:00
|
|
|
|
|
|
|
When the ``zephyr,memory-attr`` property was introduced, the
|
|
|
|
``zephyr,memory-region-mpu`` property was removed and deprecated.
|
|
|
|
|
|
|
|
The developers that are still using the deprecated property can move to the new
|
|
|
|
one by renaming the property and changing its value according to the following list:
|
|
|
|
|
|
|
|
.. code-block:: none
|
|
|
|
|
|
|
|
"RAM" -> <( DT_ARM_MPU(ATTR_MPU_RAM) )>
|
|
|
|
"RAM_NOCACHE" -> <( DT_ARM_MPU(ATTR_MPU_RAM_NOCACHE) )>
|
|
|
|
"FLASH" -> <( DT_ARM_MPU(ATTR_MPU_FLASH) )>
|
|
|
|
"PPB" -> <( DT_ARM_MPU(ATTR_MPU_PPB) )>
|
|
|
|
"IO" -> <( DT_ARM_MPU(ATTR_MPU_IO) )>
|
|
|
|
"EXTMEM" -> <( DT_ARM_MPU(ATTR_MPU_EXTMEM) )>
|
|
|
|
|
2023-09-23 23:34:32 +08:00
|
|
|
Memory Attributes Heap Allocator
|
|
|
|
********************************
|
|
|
|
|
|
|
|
It is possible to leverage the memory attribute property ``zephyr,memory-attr``
|
|
|
|
to define and create a set of memory heaps from which the user can allocate
|
|
|
|
memory from with certain attributes / capabilities.
|
|
|
|
|
|
|
|
When the :kconfig:option:`CONFIG_MEM_ATTR_HEAP` is set, every region marked
|
everywhere: replace double words
import os
import re
common_words = set([
'about', 'after', 'all', 'also', 'an', 'and',
'any', 'are', 'as', 'at',
'be', 'because', 'but', 'by', 'can', 'come',
'could', 'day', 'do', 'even',
'first', 'for', 'get', 'give', 'go', 'has',
'have', 'he', 'her',
'him', 'his', 'how', 'I', 'in', 'into', 'it',
'its', 'just',
'know', 'like', 'look', 'make', 'man', 'many',
'me', 'more', 'my', 'new',
'no', 'not', 'now', 'of', 'one', 'only', 'or',
'other', 'our', 'out',
'over', 'people', 'say', 'see', 'she', 'so',
'some', 'take', 'tell', 'than',
'their', 'them', 'then', 'there', 'these',
'they', 'think',
'this', 'time', 'two', 'up', 'use', 'very',
'want', 'was', 'way',
'we', 'well', 'what', 'when', 'which', 'who',
'will', 'with', 'would',
'year', 'you', 'your'
])
valid_extensions = set([
'c', 'h', 'yaml', 'cmake', 'conf', 'txt', 'overlay',
'rst', 'dtsi',
'Kconfig', 'dts', 'defconfig', 'yml', 'ld', 'sh', 'py',
'soc', 'cfg'
])
def filter_repeated_words(text):
# Split the text into lines
lines = text.split('\n')
# Combine lines into a single string with unique separator
combined_text = '/*sep*/'.join(lines)
# Replace repeated words within a line
def replace_within_line(match):
return match.group(1)
# Regex for matching repeated words within a line
within_line_pattern =
re.compile(r'\b(' +
'|'.join(map(re.escape, common_words)) +
r')\b\s+\b\1\b')
combined_text = within_line_pattern.
sub(replace_within_line, combined_text)
# Replace repeated words across line boundaries
def replace_across_lines(match):
return match.group(1) + match.group(2)
# Regex for matching repeated words across line boundaries
across_lines_pattern = re.
compile(r'\b(' + '|'.join(
map(re.escape, common_words)) +
r')\b(\s*[*\/\n\s]*)\b\1\b')
combined_text = across_lines_pattern.
sub(replace_across_lines, combined_text)
# Split the text back into lines
filtered_text = combined_text.split('/*sep*/')
return '\n'.join(filtered_text)
def process_file(file_path):
with open(file_path, 'r', encoding='utf-8') as file:
text = file.read()
new_text = filter_repeated_words(text)
with open(file_path, 'w', encoding='utf-8') as file:
file.write(new_text)
def process_directory(directory_path):
for root, dirs, files in os.walk(directory_path):
dirs[:] = [d for d in dirs if not d.startswith('.')]
for file in files:
# Filter out hidden files
if file.startswith('.'):
continue
file_extension = file.split('.')[-1]
if
file_extension in valid_extensions: # 只处理指定后缀的文件
file_path = os.path.join(root, file)
print(f"Processed file: {file_path}")
process_file(file_path)
directory_to_process = "/home/mi/works/github/zephyrproject/zephyr"
process_directory(directory_to_process)
Signed-off-by: Lingao Meng <menglingao@xiaomi.com>
2024-06-22 14:28:05 +08:00
|
|
|
with one of the memory attributes listed in
|
2023-09-23 23:34:32 +08:00
|
|
|
:zephyr_file:`include/zephyr/dt-bindings/memory-attr/memory-attr-sw.h` is added
|
|
|
|
to a pool of memory heaps used for dynamic allocation of memory buffers with
|
|
|
|
certain attributes.
|
|
|
|
|
|
|
|
Here a non exhaustive list of possible attributes:
|
|
|
|
|
|
|
|
.. code-block:: none
|
|
|
|
|
|
|
|
DT_MEM_SW_ALLOC_CACHE
|
|
|
|
DT_MEM_SW_ALLOC_NON_CACHE
|
|
|
|
DT_MEM_SW_ALLOC_DMA
|
|
|
|
|
|
|
|
For example we can define several memory regions with different attributes and
|
|
|
|
use the appropriate attribute to indicate that it is possible to dynamically
|
|
|
|
allocate memory from those regions:
|
|
|
|
|
|
|
|
.. code-block:: devicetree
|
|
|
|
|
|
|
|
mem_cacheable: memory@10000000 {
|
|
|
|
compatible = "mmio-sram";
|
|
|
|
reg = <0x10000000 0x1000>;
|
|
|
|
zephyr,memory-attr = <( DT_MEM_CACHEABLE | DT_MEM_SW_ALLOC_CACHE )>;
|
|
|
|
};
|
|
|
|
|
|
|
|
mem_non_cacheable: memory@20000000 {
|
|
|
|
compatible = "mmio-sram";
|
|
|
|
reg = <0x20000000 0x1000>;
|
|
|
|
zephyr,memory-attr = <( DT_MEM_NON_CACHEABLE | ATTR_SW_ALLOC_NON_CACHE )>;
|
|
|
|
};
|
|
|
|
|
|
|
|
mem_cacheable_big: memory@30000000 {
|
|
|
|
compatible = "mmio-sram";
|
|
|
|
reg = <0x30000000 0x10000>;
|
|
|
|
zephyr,memory-attr = <( DT_MEM_CACHEABLE | DT_MEM_OOO | DT_MEM_SW_ALLOC_CACHE )>;
|
|
|
|
};
|
|
|
|
|
|
|
|
mem_cacheable_dma: memory@40000000 {
|
|
|
|
compatible = "mmio-sram";
|
|
|
|
reg = <0x40000000 0x10000>;
|
|
|
|
zephyr,memory-attr = <( DT_MEM_CACHEABLE | DT_MEM_DMA |
|
|
|
|
DT_MEM_SW_ALLOC_CACHE | DT_MEM_SW_ALLOC_DMA )>;
|
|
|
|
};
|
|
|
|
|
|
|
|
The user can then dynamically carve memory out of those regions using the
|
|
|
|
provided functions, the library will take care of allocating memory from the
|
|
|
|
correct heap depending on the provided attribute and size:
|
|
|
|
|
|
|
|
.. code-block:: c
|
|
|
|
|
|
|
|
// Init the pool
|
|
|
|
mem_attr_heap_pool_init();
|
|
|
|
|
|
|
|
// Allocate 0x100 bytes of cacheable memory from `mem_cacheable`
|
|
|
|
block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE, 0x100);
|
|
|
|
|
|
|
|
// Allocate 0x200 bytes of non-cacheable memory aligned to 32 bytes
|
|
|
|
// from `mem_non_cacheable`
|
|
|
|
block = mem_attr_heap_aligned_alloc(ATTR_SW_ALLOC_NON_CACHE, 0x100, 32);
|
|
|
|
|
|
|
|
// Allocate 0x100 bytes of cacheable and dma-able memory from `mem_cacheable_dma`
|
|
|
|
block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE | DT_MEM_SW_ALLOC_DMA, 0x100);
|
|
|
|
|
|
|
|
When several regions are marked with the same attributes, the memory is allocated:
|
|
|
|
|
|
|
|
1. From the regions where the ``zephyr,memory-attr`` property has the requested
|
|
|
|
property (or properties).
|
|
|
|
|
|
|
|
2. Among the regions as at point 1, from the smallest region if there is any
|
|
|
|
unallocated space left for the requested size
|
|
|
|
|
|
|
|
3. If there is not enough space, from the next bigger region able to
|
|
|
|
accommodate the requested size
|
|
|
|
|
|
|
|
The following example shows the point 3:
|
|
|
|
|
|
|
|
.. code-block:: c
|
|
|
|
|
|
|
|
// This memory is allocated from `mem_non_cacheable`
|
2024-06-24 19:26:11 +08:00
|
|
|
block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_NON_CACHE, 0x100);
|
2023-09-23 23:34:32 +08:00
|
|
|
|
|
|
|
// This memory is allocated from `mem_cacheable_big`
|
|
|
|
block = mem_attr_heap_alloc(DT_MEM_SW_ALLOC_CACHE, 0x5000);
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
The framework is assuming that the memory regions used to create the heaps
|
|
|
|
are usable by the code and available at init time. The user must take of
|
|
|
|
initializing and setting the memory area before calling
|
|
|
|
:c:func:`mem_attr_heap_pool_init`.
|
|
|
|
|
|
|
|
That means that the region must be correctly configured in terms of MPU /
|
|
|
|
MMU (if needed) and that an actual heap can be created out of it, for
|
|
|
|
example by leveraging the ``zephyr,memory-region`` property to create a
|
|
|
|
proper linker section to accommodate the heap.
|
|
|
|
|
dt: Make zephyr,memory-attr a capabilities bitmask
This is the final step in making the `zephyr,memory-attr` property
actually useful.
The problem with the current implementation is that `zephyr,memory-attr`
is an enum type, this is making very difficult to use that to actually
describe the memory capabilities. The solution proposed in this PR is to
use the `zephyr,memory-attr` property as an OR-ed bitmask of memory
attributes.
With the change proposed in this PR it is possible in the DeviceTree to
mark the memory regions with a bitmask of attributes by using the
`zephyr,memory-attr` property. This property and the related memory
region can then be retrieved at run-time by leveraging a provided helper
library or the usual DT helpers.
The set of general attributes that can be specified in the property are
defined and explained in
`include/zephyr/dt-bindings/memory-attr/memory-attr.h` (the list can be
extended when needed).
For example, to mark a memory region in the DeviceTree as volatile,
non-cacheable, out-of-order:
mem: memory@10000000 {
compatible = "mmio-sram";
reg = <0x10000000 0x1000>;
zephyr,memory-attr = <( DT_MEM_VOLATILE |
DT_MEM_NON_CACHEABLE |
DT_MEM_OOO )>;
};
The `zephyr,memory-attr` property can also be used to set
architecture-specific custom attributes that can be interpreted at run
time. This is leveraged, among other things, to create MPU regions out
of DeviceTree defined memory regions on ARM, for example:
mem: memory@10000000 {
compatible = "mmio-sram";
reg = <0x10000000 0x1000>;
zephyr,memory-region = "NOCACHE_REGION";
zephyr,memory-attr = <( DT_ARM_MPU(ATTR_MPU_RAM_NOCACHE) )>;
};
See `include/zephyr/dt-bindings/memory-attr/memory-attr-mpu.h` to see
how an architecture can define its own special memory attributes (in
this case ARM MPU).
The property can also be used to set custom software-specific
attributes. For example we can think of marking a memory region as
available to be used for memory allocation (not yet implemented):
mem: memory@10000000 {
compatible = "mmio-sram";
reg = <0x10000000 0x1000>;
zephyr,memory-attr = <( DT_MEM_NON_CACHEABLE |
DT_MEM_SW_ALLOCATABLE )>;
};
Or maybe we can leverage the property to specify some alignment
requirements for the region:
mem: memory@10000000 {
compatible = "mmio-sram";
reg = <0x10000000 0x1000>;
zephyr,memory-attr = <( DT_MEM_CACHEABLE |
DT_MEM_SW_ALIGN(32) )>;
};
The conventional and recommended way to deal and manage with memory
regions marked with attributes is by using the provided `mem-attr`
helper library by enabling `CONFIG_MEM_ATTR` (or by using the usual DT
helpers).
When this option is enabled the list of memory regions and their
attributes are compiled in a user-accessible array and a set of
functions is made available that can be used to query, probe and act on
regions and attributes, see `include/zephyr/mem_mgmt/mem_attr.h`
Note that the `zephyr,memory-attr` property is only a descriptive
property of the capabilities of the associated memory region, but it
does not result in any actual setting for the memory to be set. The
user, code or subsystem willing to use this information to do some work
(for example creating an MPU region out of the property) must use either
the provided `mem-attr` library or the usual DeviceTree helpers to
perform the required work / setting.
Signed-off-by: Carlo Caione <ccaione@baylibre.com>
2023-08-16 18:48:26 +08:00
|
|
|
API Reference
|
|
|
|
*************
|
|
|
|
|
|
|
|
.. doxygengroup:: memory_attr_interface
|
2023-09-23 23:34:32 +08:00
|
|
|
.. doxygengroup:: memory_attr_heap
|