-
Notifications
You must be signed in to change notification settings - Fork 6.9k
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: nrf_qspi_nor: unaligned read offset & read lenght #26772
drivers: flash: nrf_qspi_nor: unaligned read offset & read lenght #26772
Conversation
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.
Just started looking.
Pleas squash fixing commits to them right fix-target commit.
a42069b
to
7d452f9
Compare
I think test added here might be a seed of general flash driver test suite we can extend in another PR. |
drivers/flash/nrf_qspi_nor.c
Outdated
if (res != NRFX_SUCCESS) { | ||
return res; | ||
} | ||
memcpy(dptr, buf + flash_offset, flash_prefix); |
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.
Perhaps using buf[4 - flash_prefix]
would be clearer, as you are copying an ending part of the buffer (you could also get rid of flash_offset
then).
You could define some label for this 4
(WORD_SIZE
?). It is used multiple times in the code and in some places it looks quite magical.
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.
Replaced.
#include <ztest.h> | ||
#include <drivers/flash.h> | ||
|
||
#if (CONFIG_NORDIC_QSPI_NOR - 0) |
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 test is dedicated to the nrf_qspi_nor driver, isn't it? Is there a point of checking if this driver is enabled?
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.
Deleted.
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.
Doesn't seem to be changed.
07fd283 has a good solution for identifying the generic flash device, could be used here.
#define EXPECTED_SIZE 256 | ||
|
||
struct device *flash_dev; | ||
int rc; |
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.
What's the point of having this as global variable?
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.
Changed to local.
#define LENGTH 17 | ||
#define EXPECTED_SIZE 256 | ||
|
||
struct device *flash_dev; |
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.
static
missing.
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.
Added.
CONFIG_ZTEST=y | ||
CONFIG_NORDIC_QSPI_NOR=y | ||
CONFIG_FLASH=y | ||
CONFIG_SERIAL=y |
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.
Why do you need it here?
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.
Only in debug purposes. Will delete it.
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.
What was "it"? Nothing seems to have changed.
ztest_unit_test(test_erase), | ||
ztest_unit_test(test_read_after_erase), | ||
ztest_unit_test(test_read_unaligned_address) |
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 don't think I get the idea of this test. What's the point here in erasing a sector and then checking if four bytes of it have the value of 0xff
?
I think it would be better to write the pattern to flash only if it is not already written there, in test_setup()
. And then in the actual test case just perform the reads.
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 don't think I get the idea of this test. What's the point here in erasing a sector and then checking if four bytes of it have the value of 0xff?
It's only my suggestion for testing flash_erase
function.
I think it would be better to write the pattern to flash only if it is not already written there, in test_setup(). And then in the actual test case just perform the reads.
Ok, flash_erase
only if there is something.
for (off_t ad_o = 0; ad_o < 4; ad_o++) { | ||
/* buffer offset */ | ||
for (off_t buf_o = 0; buf_o < 4; buf_o++) { | ||
rc = flash_read(flash_dev, |
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.
The buffer should be cleared before the read. To avoid taking the previous read result as the current one if for some reason the current read request is for example ignored.
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.
Added.
9a298af
to
e15fd3e
Compare
be67f20
to
db31578
Compare
tests/drivers/flash/src/main.c
Outdated
page_info.start_offset + ad_o, | ||
buf + buf_o, LENGTH); | ||
zassert_equal(rc, 0, "Cannot read flash"); | ||
zassert_equal(memcmp(buf + buf_o, |
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.
There is a lot of pointer/offset operations happening, it may by worth to actually use encapsulate test buffer in bigger buffer and prefix it and postfix it with canaries to check if writes beyond the buffer does not happen.
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.
There were read buffer overflow indeed, only in one case. Added canaries around buffer in tests.
db31578
to
84e643b
Compare
62d1f99
to
6d2a369
Compare
tests/drivers/flash/src/main.c
Outdated
|
||
void test_main(void) | ||
{ | ||
ztest_test_suite(nrf_qspi_nor_test, |
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.
nip: change name to flash_driver_test
as it is generic, shell pass for any flash device in near feature.
@pabigot @anangl @de-nordic can you take another look please? |
@carlescufi @de-nordic @pabigot @anangl I think this is ready to be merged. After this PR will be merged we can extend the test-suite added here, to be adapted by other SoC and add more test cases for cover flash API implementation testing well. |
drivers/flash/nrf_qspi_nor.c
Outdated
} | ||
|
||
/* perform shift in RAM */ | ||
if (flash_prefix - dest_prefix != 0) { |
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.
The arithmetic expression should be in parentheses.
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.
Added.
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.
Thanks for testing with canaries.
I have left one style issue open, that is lack of parentheses around arithmetic expression, otherwise I think it is ok.
606b2fd
to
15ac353
Compare
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.
Just an initial pass. There are a large number of comments where @MSyc-NS commented four days ago that a change had been made, but no change is visible in the current content. Please verify those then I'll look again.
drivers/flash/nrf_qspi_nor.c
Outdated
dptr[i + shift] = dptr[i]; | ||
} | ||
} | ||
else if (shift < 0) { |
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.
put '}' and 'else {' on same line.
drivers/flash/nrf_qspi_nor.c
Outdated
} | ||
|
||
/* perform shift in RAM */ | ||
if (shift > 0) { |
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.
So why isn't this using memmove
?
CONFIG_ZTEST=y | ||
CONFIG_NORDIC_QSPI_NOR=y | ||
CONFIG_FLASH=y | ||
CONFIG_SERIAL=y |
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.
What was "it"? Nothing seems to have changed.
#include <ztest.h> | ||
#include <drivers/flash.h> | ||
|
||
#if (CONFIG_NORDIC_QSPI_NOR - 0) |
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.
Doesn't seem to be changed.
07fd283 has a good solution for identifying the generic flash device, could be used here.
Looks like fix commits were not squashed properly. Most of @pabigot requests were full filled but need do clear commits history here. |
15ac353
to
019dabd
Compare
I made changes, but not committed it properly. I'm sorry, it's fixed now. |
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; my bad on the previous review: when I see more than two or three commits I look at them individually, which causes confusion when the comments aren't addressed in the same commit.
The detection of the appropriate flash device using the technique in 07fd283 can wait until this test is generalized to other devices.
flash_prefix = size; | ||
} | ||
|
||
off_t dest_prefix = (WORD_SIZE - (off_t)dptr % WORD_SIZE) % WORD_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.
This trailing % WORD_SIZE
is redundant.
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.
It is not redundant; dest_prefix
should take the value of [0 ... 3], not [0 ... 4]. If dest_prefix
has value of 4, it should be reduced to 0.
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.
Ah, right, I missed that case.
But what about flash_prefix
then, shouldn't it be calculated the same way?
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.
Yes, should be. Will add.
drivers/flash/nrf_qspi_nor.c
Outdated
static inline nrfx_err_t read_non_aligned(struct device *dev, off_t addr, | ||
void *dest, size_t size) | ||
{ | ||
uint8_t __aligned(4) buf[WORD_SIZE * 2]; |
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.
Why not __aligned(WORD_SIZE)
?
drivers/flash/nrf_qspi_nor.c
Outdated
/* perform shift in RAM */ | ||
if ((flash_prefix - dest_prefix) != 0) { | ||
memmove(dptr + flash_prefix, dptr + dest_prefix, flash_middle); | ||
} |
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 is only needed when some "middle" has been actually read, so it would be better to place it in the if
block above.
drivers/flash/nrf_qspi_nor.c
Outdated
} | ||
|
||
/* perform shift in RAM */ | ||
if ((flash_prefix - dest_prefix) != 0) { |
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.
Maybe just flash_prefix != dest_prefix
?
if (!is_buf_clear) { | ||
/* erase page */ | ||
rc = flash_erase(flash_dev, page_info.start_offset, |
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.
Is it really needed to always have this flash region cleared for this test?
I think you could skip this erasing and writing of the expected pattern to flash when it happens to be already written there (and this will be the case when this test is for example performed several times in a row).
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 assumed that it is type of the test - erase and check if done properly. It is not necessary, but warn if something is wrong.
I only considered if move it to the separate test.
rc = flash_write(flash_dev, | ||
page_info.start_offset, | ||
expected, EXPECTED_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.
Won't this be a problem if the expected
buffer happens to be not aligned to the word boundary?
019dabd
to
eb33fab
Compare
drivers/flash/nrf_qspi_nor.c
Outdated
uint8_t __aligned(WORD_SIZE) buf[WORD_SIZE * 2]; | ||
uint8_t *dptr = dest; | ||
|
||
off_t flash_prefix = WORD_SIZE - (addr % WORD_SIZE) % WORD_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.
You need to use parentheses here. Otherwise, the second modulo operation will be performed before the subtraction, and consequently it will be useless.
off_t flash_prefix = WORD_SIZE - (addr % WORD_SIZE) % WORD_SIZE; | |
off_t flash_prefix = (WORD_SIZE - (addr % WORD_SIZE)) % WORD_SIZE; |
Added function read_non_aligned that reads data under non-aligned flash addres to non-aligned read buffer of any size. Signed-off-by: Mateusz Syc <Mateusz.Syc@nordicsemi.no>
Test include non-aligned read in nrf_qspi_nor flash and SoC flash memory to buffer with variable size. It checks all possible variants of alignment and size. Signed-off-by: Mateusz Syc <Mateusz.Syc@nordicsemi.no>
eb33fab
to
1d06546
Compare
This PR add support for unaligned read from nrf_qspi flash memory.
User does not pay attention if address and read buffer are DWORD
aligned or read buffer length is multiply of DWORD size.
I packed all the functionality to the read_non_aligned() function.
The main concept is firstly to copy data from aligned address to the
aligned middle of the buffer. Therefore the content in the middle is
shifted to achieve the same index. Finally data from start is copied
to temporary, aligned buffer and "memcpy()" to the read buffer.
The same with the end.
I additionally suggested some test of the feature.