-
Notifications
You must be signed in to change notification settings - Fork 2.1k
drivers/mtd_flashpage: fix address mapping #17964
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
Conversation
This discussion would profit from having people around who use a platform with non-zero CPU_FLASH_BASE -- from a quick grep that'd be QN908X, LM4F120, RPx0xx and CC26xx. (could be @maribu, @fabian18 or @jeandudey from their commit history). I can sympathize with both behaviors, because
One point of concern might also be the use of FLASH_WRITABLE_INIT, which currently has no shortcut for setting up a corresponding mapped flashpage device. |
I'm just using |
I agree that Perhaps a compromise could be to have |
The STM32's also have
I'm not understanding what is meant here. Can you elaborate? |
Maybe I am misunderstanding something. IMO you cannot use the sector in mtd_mapper as an offset. This offset is set as a start from 0 and it is checked that that it is not larger than the last mtd sector. When flash had an offset this offset might not be related to any sector size. |
@Enoch247, @chrysn, @jue89, while going through the code it seems there is some inconsistentie in the flashpage driver. While working with pages the flashpage driver uses a address space of 0-N flash pages so the offset is added during operation. While working with addresses the flashpage driver is expecting cpu adresses. This is confusing. To remove this inconsistentie it would be better that the flashpage driver uses 0-flash_size address and the offset is added in the flashpage driver. There seems to be another inconsistentie in flashpage where The mtd_flashpage driver could then use a |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. If you want me to ignore this issue, please mark it with the "State: don't stale" label. Thank you for your contributions. |
I am once again playing with flash, MTD, and filesystems. I am trying to allocate a filesystem within my MCU's flash. I have attempted to use Here is why. Lets take a hypothetical MCU with and address space of 0 to 100. Let's say flash is mapped to addresses 50 to 100, and that pages are 10 bytes each (therefore mtd_flashpage_t mtd_flashpage = MTD_FLASHPAGE_INIT_VAL(4);
mtd_mapper_parent_t mtd_mapper_parent = MTD_PARENT_INIT(&mtd_flashpage.base);
mtd_mapper_region_t region1 = {
.mtd = {
.driver = &mtd_mapper_driver,
.sector_count = FLASHPAGE_NUMOF,
.pages_per_sector = 4,
.page_size = FLASHPAGE_SIZE / 4,
},
.parent = &mtd_mapper_parent,
.sector = FLASHPAGE_NUMOF,
}; This code is attempting to use I think a fix will need to either change |
I see the problem you're running into. Thanks for clarifying this. Let's ask CI what it thinks about your patch ;-) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest these minor changes:
@@ -40,6 +49,8 @@ static int _init(mtd_dev_t *dev) | |||
|
|||
static int _read(mtd_dev_t *dev, void *buf, uint32_t addr, uint32_t size) | |||
{ | |||
addr = _mtd_to_flashpage_addr(addr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say it's better not to reuse addr
here. Please change it to something like this:
addr = _mtd_to_flashpage_addr(addr); | |
uword_t addr_abs = _mtd_to_flashpage_addr(addr); |
And use addr_abs
in the implementation
|
||
return 0; | ||
} | ||
|
||
static int _write(mtd_dev_t *dev, const void *buf, uint32_t addr, uint32_t size) | ||
{ | ||
addr = _mtd_to_flashpage_addr(addr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here:
addr = _mtd_to_flashpage_addr(addr); | |
uword_t addr_abs = _mtd_to_flashpage_addr(addr); |
|
||
return 0; | ||
} | ||
|
||
int _erase(mtd_dev_t *dev, uint32_t addr, uint32_t size) | ||
{ | ||
addr = _mtd_to_flashpage_addr(addr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here:
addr = _mtd_to_flashpage_addr(addr); | |
uword_t addr_abs = _mtd_to_flashpage_addr(addr); |
@Enoch247 ping? |
Sorry. I was wrapping up a large project. I will take a look at your suggestions. |
No worries. Just wanted to be sure, you've seen the review. Take the time you need! |
@jue89 : I committed your suggestions as a fixup. I will squash when you are ready. |
Thank you for your effort and great work! Murdock complains about the MSP340. The reason: the flash page address range reaches up to the very last address within the 16-bit address space. Thus, the compiler tells us that this check if the address is larger than this number will never be true. I tried to fix this issue - and came up with a different approach by accident :-D Here is my approach. What do you think? diff --git a/drivers/mtd_flashpage/mtd_flashpage.c b/drivers/mtd_flashpage/mtd_flashpage.c
index 731d0e915d..31f7779d37 100644
--- a/drivers/mtd_flashpage/mtd_flashpage.c
+++ b/drivers/mtd_flashpage/mtd_flashpage.c
@@ -19,6 +19,7 @@
* @}
*/
+#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
@@ -29,15 +30,20 @@
#include "mtd_flashpage.h"
#include "periph/flashpage.h"
-#define MTD_FLASHPAGE_END_ADDR ((uint32_t) CPU_FLASH_BASE + (FLASHPAGE_NUMOF * FLASHPAGE_SIZE))
+#define MTD_FLASHPAGE_SIZE (FLASHPAGE_NUMOF * FLASHPAGE_SIZE)
+
+static inline bool _range_within_bounds(uint32_t addr, uint32_t size)
+{
+ return addr + size <= MTD_FLASHPAGE_SIZE;
+}
/* The MTD driver operates on an address space of 0 to N. However, the */
/* flashpage driver operates on an address space of CPU_FLASH_BASE to */
/* MTD_FLASHPAGE_END_ADDR. This function takes a MTD address and returns a */
/* flashpage address. */
-static uword_t _mtd_to_flashpage_addr(uint32_t addr)
+static void* _mtd_to_flashpage_addr(uint32_t addr)
{
- return addr + CPU_FLASH_BASE;
+ return (void*)((uword_t) addr + CPU_FLASH_BASE);
}
static int _init(mtd_dev_t *dev)
@@ -49,27 +55,26 @@ static int _init(mtd_dev_t *dev)
static int _read(mtd_dev_t *dev, void *buf, uint32_t addr, uint32_t size)
{
- const uword_t flash_addr = _mtd_to_flashpage_addr(addr);
-
- assert(flash_addr < MTD_FLASHPAGE_END_ADDR);
-
(void)dev;
#ifndef CPU_HAS_UNALIGNED_ACCESS
- if (flash_addr % sizeof(uword_t)) {
+ assert(CPU_FLASH_BASE % sizeof(uword_t));
+ if (addr % sizeof(uword_t)) {
return -EINVAL;
}
#endif
- memcpy(buf, (void *)flash_addr, size);
+ if (!_range_within_bounds(addr, size)) {
+ return -EOVERFLOW;
+ }
+
+ memcpy(buf, _mtd_to_flashpage_addr(addr), size);
return 0;
}
static int _write(mtd_dev_t *dev, const void *buf, uint32_t addr, uint32_t size)
{
- const uword_t flash_addr = _mtd_to_flashpage_addr(addr);
-
(void)dev;
#ifndef CPU_HAS_UNALIGNED_ACCESS
@@ -77,30 +82,30 @@ static int _write(mtd_dev_t *dev, const void *buf, uint32_t addr, uint32_t size)
return -EINVAL;
}
#endif
- if (flash_addr % FLASHPAGE_WRITE_BLOCK_ALIGNMENT) {
+ assert(CPU_FLASH_BASE % FLASHPAGE_WRITE_BLOCK_ALIGNMENT);
+ if (addr % FLASHPAGE_WRITE_BLOCK_ALIGNMENT) {
return -EINVAL;
}
if (size % FLASHPAGE_WRITE_BLOCK_SIZE) {
return -EOVERFLOW;
}
- if (flash_addr + size > MTD_FLASHPAGE_END_ADDR) {
+ if (!_range_within_bounds(addr, size)) {
return -EOVERFLOW;
}
- flashpage_write((void *)flash_addr, buf, size);
+ flashpage_write(_mtd_to_flashpage_addr(addr), buf, size);
return 0;
}
int _erase(mtd_dev_t *dev, uint32_t addr, uint32_t size)
{
- const uword_t flash_addr = _mtd_to_flashpage_addr(addr);
size_t sector_size = dev->page_size * dev->pages_per_sector;
if (size % sector_size) {
return -EOVERFLOW;
}
- if (flash_addr + size > MTD_FLASHPAGE_END_ADDR) {
+ if (!_range_within_bounds(addr, size)) {
return -EOVERFLOW;
}
if (addr % sector_size) {
@@ -108,7 +113,7 @@ int _erase(mtd_dev_t *dev, uint32_t addr, uint32_t size)
}
for (size_t i = 0; i < size; i += sector_size) {
- flashpage_erase(flashpage_page((void *)(flash_addr + i)));
+ flashpage_erase(flashpage_page(_mtd_to_flashpage_addr(addr + i)));
}
return 0; |
apply sugestion from here: RIOT-OS#17964 (comment)
Your patch looks good to me. I had two comments on it. I pushed it as a fixup commit so that I could add those comments. |
@@ -29,7 +30,21 @@ | |||
#include "mtd_flashpage.h" | |||
#include "periph/flashpage.h" | |||
|
|||
#define MTD_FLASHPAGE_END_ADDR ((uint32_t) CPU_FLASH_BASE + (FLASHPAGE_NUMOF * FLASHPAGE_SIZE)) | |||
#define MTD_FLASHPAGE_SIZE (FLASHPAGE_NUMOF * FLASHPAGE_SIZE) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jue89 MTD_FLASHPAGE_SIZE
is a bit confusing as there is already a FLASHPAGE_SIZE
, but they mean different things.
MTD_FLASHPAGE_SIZE
- size of the entire flashFLASHPAGE_SIZE
- size of a single flashpage
Perhaps a better name could help future readers? Perhaps something could be added to periph/flashpage.h
and just used here instead? Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is a perfect example for bad naming :D
... back when I wrote this suggestion my mind came up with it's the size
of the storage provided by mtd_flashpage
.
Currently I have very little time to come up with an example, sry! But your idea sounds good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I will make the change.
@@ -65,18 +82,18 @@ static int _write(mtd_dev_t *dev, const void *buf, uint32_t addr, uint32_t size) | |||
return -EINVAL; | |||
} | |||
#endif | |||
assert(CPU_FLASH_BASE % FLASHPAGE_WRITE_BLOCK_ALIGNMENT); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jue89 : Not sure why this needed to be added. Is this something that should be asserted elsewhere (maybe in the flashpage
driver)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This assert just makes sure that just testing the addr
(which is an offset starting from CPU_FLASH_BASE) for alignment is a valid thing to do. Otherwise we must check CPU_FLASH_BASE + addr
for alignment during runtime.
I asserted this at this point because it checks assumptions made one line later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I suggest making it a static_assert
then, and maybe a comment to explain its purpose. If you agree, I will make the change.
Alternatively I could just split out the changes to |
I agree, that's what this MR aims to fix. That is, it remaps the addresses used by mtd_flashpage to be 0 based. This is because, mtd_mapper has assumptions that all mtd devices' address space start at 0. See comment above. |
Does the (now merged) solution form #19258 work for you? |
I believe it will. Closing this PR. |
Contribution description
The MTD driver assumes an address space 0-N. The flashpage driver operates on CPU's address space. The
mtd_flashpage
driver does not account for this. It passes addresses strait through. The entire CPU's address space is mapped as an MTD, flash, RAM, registers, and all. After looking attests/mtd_flashpage/main.c
I believe the intent was to havemtd_flashpage
do this mapping.This PR is a DRAFT meant to trigger a discussion of if it is the right fix. One could argue that breaking the current behavior is too disruptive of existing applications, and that the right fix would be to adopt the current behavior of the driver and change the tests to match it. There is also value in the current behavior. Many applications using
mtd_flashpage
will also usemtd_mapper
. Sincemtd_mapper
needs a starting sector, it is convenient to set this in terms of the CPU's address spaceTesting procedure
TBD
Issues/PRs references
none known