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: flash: sam: Redesign controller to fully utilize flash page layout #64215

Conversation

bjarki-trackunit
Copy link
Collaborator

@bjarki-trackunit bjarki-trackunit commented Oct 21, 2023

This PR redesigns the atmel sam flash controller to fully utilize the flash page layout and capabilities of each individual soc.

An example is the ATSAM4E series socs, they have a flash layout like:

|--------------------|
| 8 Kbytes           |  erase block size = 2048
|--------------------|
| 8 Kbytes           |  erase block size = 2048
|--------------------|
| 48 Kbytes          |  erase block size = 4096
|--------------------|
| 64 Kbytes          |  erase block size = 4096
|--------------------|
| ...                |

and a write block size of 8 bytes.

This PR adds a new flash-pages cell property which is used to describe this layout fully:

flash0: flash@400000 {
	compatible = "atmel,sam-flash", "soc-nv-flash";
	write-block-size = <8>;
	flash-pages = <&eefc 8 2048>, <&eefc 252 4096>;
};

Comparing this to the ATSAME70 series

|--------------------|
| 8 Kbytes           |  erase block size = 2048
|--------------------|
| 8 Kbytes           |  erase block size = 2048
|--------------------|
| 112 Kbytes         |  erase block size = 8192
|--------------------|
| 128 Kbytes         |  erase block size = 8192
|--------------------|
| ...                |

and a write block size of 16 bytes.

It is described as

flash0: flash@400000 {
	compatible = "atmel,sam-flash", "soc-nv-flash";
	write-block-size = <16>;
	flash-pages = <&eefc 8 2048>, <&eefc 252 8192>;
};

The redesigned driver is based on the flash_page_layout.c driver to avoid duplicate code. The redesigned flash driver is still a bit naive, it will be expanded with logging and error handling.

@Laczen
Copy link
Collaborator

Laczen commented Oct 22, 2023

Hi @bjarki-trackunit, in other flash drivers this is done by creating the correct page_layout array. For the atmel sam flash there would be two entries: one entry for the smaller pages and one for the larger pages.

@bjarki-trackunit
Copy link
Collaborator Author

bjarki-trackunit commented Oct 22, 2023

Hi @bjarki-trackunit, in other flash drivers this is done by creating the correct page_layout array. For the atmel sam flash there would be two entries: one entry for the smaller pages and one for the larger pages.

That is what the redesigned driver is doing internally :)

#define SAM_FLASH_DEVICE DT_INST(0, atmel_sam_flash)
#define SAM_FLASH_PAGES_LAYOUT(node_id, prop, idx) \
{ \
.pages_count = DT_PHA_BY_IDX(node_id, prop, idx, pages_count), \
.pages_size = DT_PHA_BY_IDX(node_id, prop, idx, pages_size), \
}
#define SAM_FLASH_PAGES_LAYOUTS \
DT_FOREACH_PROP_ELEM_SEP(SAM_FLASH_DEVICE, flash_pages, SAM_FLASH_PAGES_LAYOUT, (,))
#define SAM_FLASH_CONTROLLER(inst) \
struct flash_pages_layout sam_flash_pages_layouts##inst[] = { \
SAM_FLASH_PAGES_LAYOUTS \
}; \

Its using the new cells in the devicetree to create the proper page_layout array :)
For the ATSAM4E, the struct flash_pages_layout array expands to:

struct flash_pages_layout sam_flash_pages_layouts0[] = {
	{
		.pages_count = 8,
		.pages_size = 2048,
	},
	{
		.pages_count = 252,
		.pages_size = 4096,
	},
};	

@bjarki-trackunit bjarki-trackunit marked this pull request as ready for review October 22, 2023 10:05
@zephyrbot zephyrbot added area: Flash platform: Microchip SAM Microchip SAM Platform (formerly Atmel SAM) area: Devicetree Binding PR modifies or adds a Device Tree binding labels Oct 22, 2023
@bjarki-trackunit bjarki-trackunit requested review from Laczen and removed request for pdgendt, stephanosio, mnkp and attie-argentum October 22, 2023 10:06
@Laczen
Copy link
Collaborator

Laczen commented Oct 22, 2023

@bjarki-trackunit, is the proposal to move the definition of flash layout from the driver to the dts ?

It would be needed to change "flash-pages" to "erase-blocks".

What is the meaning of "&eefc" ?

@bjarki-trackunit
Copy link
Collaborator Author

bjarki-trackunit commented Oct 22, 2023

@bjarki-trackunit, is the proposal to move the definition of flash layout from the driver to the dts ?

Correct, just like write-block-size and read-block-size (which is essentially the erase block size).

It would be needed to change "flash-pages" to "erase-blocks".

I agree with erase-blocks :)

What is the meaning of "&eefc" ?

Its the node label of the flash-controller, it defines the cell properties of the flash-pages property :)

Copy link
Member

@nandojve nandojve left a comment

Choose a reason for hiding this comment

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

Hi @bjarki-trackunit ,

Nice!

It will took time from my side to do a proper review and test the flash_sam.c.

Comment on lines 13 to 16

"#flash-page-cells":
type: int
const: 2
Copy link
Member

Choose a reason for hiding this comment

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

It will be necessary the documentation with examples. Remember that devicetree should be self explanatory and readers should not go to the datasheet to have a full understanding.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Agreed

@@ -0,0 +1,18 @@
description: Atmel SAM flash area

compatible: "atmel,sam-flash"
Copy link
Member

Choose a reason for hiding this comment

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

provide full documentation with examples

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Agreed, wanted to get some feedback first :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@Laczen
Copy link
Collaborator

Laczen commented Jan 20, 2024

For external flash, it should be a flash controller, with a flash area, just like internal flash :)

Could it not just be part of the device yaml?

@bjarki-trackunit
Copy link
Collaborator Author

For external flash, it should be a flash controller, with a flash area, just like internal flash :)

Could it not just be part of the device yaml?

Well, the device is a flash controller, right?

@Laczen
Copy link
Collaborator

Laczen commented Jan 20, 2024

@bjarki-trackunit, maybe a future addition could be to fall back to an erase-block-size based flash page layout (the pre PR layout) when erase-blocks is not specified.

@de-nordic
Copy link
Collaborator

For external flash, it should be a flash controller, with a flash area, just like internal flash :)

Could it not just be part of the device yaml?

Well, the device is a flash controller, right?

Unfortunately.

de-nordic
de-nordic previously approved these changes Jan 22, 2024
Copy link
Collaborator

@de-nordic de-nordic left a comment

Choose a reason for hiding this comment

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

Some nits, but generally OK.

Comment on lines +119 to +146
if ((offset >= 0) && ((offset + len) <= config->area_size)) {
return true;
Copy link
Collaborator

Choose a reason for hiding this comment

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

with significantly large offset and len the (offset + len) may rollover to something that is <= area_size.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added a check to validate the addition of offset and len are safe

static bool sam_flash_validate_offset_len(off_t offset, size_t len)
{
if (offset < 0) {
return false;
}
if ((offset + len) < len) {
return false;
}
return true;
}

Comment on lines 134 to 135
if (((offset % config->parameters.write_block_size) == 0) &&
((len % config->parameters.write_block_size) == 0)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

'%' is division, so probably takes more cycles than binary operations that could be used here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Changed to use binary operations as the value will always be aligned with an exponent of base 2

static bool sam_flash_aligned(size_t value, size_t alignment)
{
return (value & (alignment - 1)) == 0;
}

drivers/flash/flash_sam.c Show resolved Hide resolved
@bjarki-trackunit bjarki-trackunit force-pushed the rewrite_atmel_sam_flash_controller branch 2 times, most recently from be18b9d to 84b6ed9 Compare January 23, 2024 05:52
This commit updates the driver to use the flash layout pages,
rewriting it to utilize the flash_page_layout.c driver to
avoid duplicate code.

Signed-off-by: Bjarki Arge Andreasen <bjarkix123@gmail.com>
Add log messages to help diagnose and understand flash
driver behavior.

Signed-off-by: Bjarki Arge Andreasen <bjarkix123@gmail.com>
Use interrupt to wait for flash controller to finish
its command and become ready.

Signed-off-by: Bjarki Arge Andreasen <bjarkix123@gmail.com>
@bjarki-trackunit bjarki-trackunit force-pushed the rewrite_atmel_sam_flash_controller branch from 84b6ed9 to a06dfce Compare January 23, 2024 06:08
@bjarki-trackunit
Copy link
Collaborator Author

Update

I have addressed the issues brought up by @pdgendt and @de-nordic :)

pdgendt
pdgendt previously approved these changes Jan 23, 2024
Copy link
Collaborator

@pdgendt pdgendt left a comment

Choose a reason for hiding this comment

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

Thanks! Tested on sam4s.

@Laczen
Copy link
Collaborator

Laczen commented Jan 23, 2024

@bjarki-trackunit, I have some annoying remark.

The PR adds a test page_layout that erases and writes to flash. A page_layout test should focus on the routines that are provided by the page_layout api: flash_get_page_info_by_offs(), flash_get_page_info_by_idx() and flash_page_foreach. The correct functionality for each of these routines should be tested and if possible without any erase/write. Also this test should be carried out in userspace if possible (at the moment the flash_page_foreach is not supported for userspace access).

Could the test be renamed into something else so that can leave the name page_layout for the test of the page_layout api?

@bjarki-trackunit
Copy link
Collaborator Author

Could the test be renamed into something else so that can leave the name page_layout for the test of the page_layout api?

sure, I have no strong feeling on the name, I could name it erase_write_boundary or just erase_write_validate, or maybe you have a good name?

@Laczen
Copy link
Collaborator

Laczen commented Jan 23, 2024

Could the test be renamed into something else so that can leave the name page_layout for the test of the page_layout api?

sure, I have no strong feeling on the name, I could name it erase_write_boundary or just erase_write_validate, or maybe you have a good name?

What about erase_blocks ?

Add test suite which tests writing to and erasing all pages,
of any size defined by the page layout.

If the test is built with MCUBOOT, the test will jump into the
application, then run write/erase/boundary tests on the
bootload partition. If MCUBOOT is not selected, the test will
target the slot1 partition instead, performing the same tests.

Signed-off-by: Bjarki Arge Andreasen <bjarki@arge-andreasen.me>
@bjarki-trackunit
Copy link
Collaborator Author

renamed page_layout test to erase_blocks

@Laczen
Copy link
Collaborator

Laczen commented Jan 23, 2024

renamed page_layout test to erase_blocks

Maybe in the long run we should move all present flash tests under functional and add a separate api folder for api tests (that also verify the userspace access).

@fabiobaltieri fabiobaltieri merged commit 592647c into zephyrproject-rtos:main Jan 23, 2024
19 checks passed
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 platform: Microchip SAM Microchip SAM Platform (formerly Atmel SAM)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants