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: nrf_qspi_nor: unaligned read offset & read lenght #26772

Merged
merged 2 commits into from
Jul 20, 2020

Conversation

m-syc
Copy link
Contributor

@m-syc m-syc commented Jul 9, 2020

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.

@nvlsianpu nvlsianpu self-requested a review July 9, 2020 14:35
@github-actions github-actions bot added the area: Tests Issues related to a particular existing or missing test label Jul 9, 2020
Copy link
Collaborator

@nvlsianpu nvlsianpu left a 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.

drivers/flash/nrf_qspi_nor.c Outdated Show resolved Hide resolved
@nvlsianpu nvlsianpu requested review from anangl and kamlaz July 10, 2020 11:53
@m-syc m-syc force-pushed the non_aligned_flash_read branch from a42069b to 7d452f9 Compare July 10, 2020 12:20
drivers/flash/nrf_qspi_nor.c Outdated Show resolved Hide resolved
drivers/flash/nrf_qspi_nor.c Outdated Show resolved Hide resolved
@nvlsianpu nvlsianpu requested a review from carlescufi July 10, 2020 13:01
@nvlsianpu
Copy link
Collaborator

I think test added here might be a seed of general flash driver test suite we can extend in another PR.
I suggest to move it to tests/drivers/flash/flash/ directory. Will comment on changes required in its code.

tests/drivers/flash/nrf_qspi_nor/src/main.c Outdated Show resolved Hide resolved
tests/drivers/flash/nrf_qspi_nor/src/main.c Outdated Show resolved Hide resolved
tests/drivers/flash/nrf_qspi_nor/src/main.c Outdated Show resolved Hide resolved
if (res != NRFX_SUCCESS) {
return res;
}
memcpy(dptr, buf + flash_offset, flash_prefix);
Copy link
Member

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.

Copy link
Contributor Author

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)
Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Deleted.

Copy link
Collaborator

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;
Copy link
Member

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?

Copy link
Contributor Author

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;
Copy link
Member

Choose a reason for hiding this comment

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

static missing.

Copy link
Contributor Author

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
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Collaborator

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.

Comment on lines 86 to 88
ztest_unit_test(test_erase),
ztest_unit_test(test_read_after_erase),
ztest_unit_test(test_read_unaligned_address)
Copy link
Member

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.

Copy link
Contributor Author

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,
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added.

drivers/flash/nrf_qspi_nor.c Outdated Show resolved Hide resolved
@m-syc m-syc force-pushed the non_aligned_flash_read branch 2 times, most recently from 9a298af to e15fd3e Compare July 15, 2020 11:30
@m-syc m-syc force-pushed the non_aligned_flash_read branch 2 times, most recently from be67f20 to db31578 Compare July 15, 2020 13:09
page_info.start_offset + ad_o,
buf + buf_o, LENGTH);
zassert_equal(rc, 0, "Cannot read flash");
zassert_equal(memcmp(buf + buf_o,
Copy link
Collaborator

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.

Copy link
Contributor Author

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.

@m-syc m-syc marked this pull request as ready for review July 15, 2020 15:03
@m-syc m-syc requested review from nashif and pabigot as code owners July 15, 2020 15:03
@m-syc m-syc force-pushed the non_aligned_flash_read branch from db31578 to 84e643b Compare July 15, 2020 15:22
@m-syc m-syc force-pushed the non_aligned_flash_read branch from 62d1f99 to 6d2a369 Compare July 17, 2020 06:45
@m-syc m-syc requested a review from anangl July 17, 2020 08:33
@m-syc m-syc requested review from nvlsianpu, de-nordic and pabigot July 17, 2020 08:34

void test_main(void)
{
ztest_test_suite(nrf_qspi_nor_test,
Copy link
Collaborator

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.

@carlescufi
Copy link
Member

@pabigot @anangl @de-nordic can you take another look please?

@nvlsianpu
Copy link
Collaborator

@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.

}

/* perform shift in RAM */
if (flash_prefix - dest_prefix != 0) {
Copy link
Collaborator

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added.

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.

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.

@m-syc m-syc force-pushed the non_aligned_flash_read branch from 606b2fd to 15ac353 Compare July 17, 2020 11:12
Copy link
Collaborator

@pabigot pabigot left a 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.

dptr[i + shift] = dptr[i];
}
}
else if (shift < 0) {
Copy link
Collaborator

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.

}

/* perform shift in RAM */
if (shift > 0) {
Copy link
Collaborator

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
Copy link
Collaborator

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)
Copy link
Collaborator

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.

@nvlsianpu
Copy link
Collaborator

Looks like fix commits were not squashed properly. Most of @pabigot requests were full filled but need do clear commits history here.
@MSyc-NS Please squash fix commits to proper parent commits.

@m-syc m-syc force-pushed the non_aligned_flash_read branch from 15ac353 to 019dabd Compare July 17, 2020 16:57
@m-syc
Copy link
Contributor Author

m-syc commented Jul 17, 2020

@pabigot

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.

I made changes, but not committed it properly. I'm sorry, it's fixed now.

Copy link
Collaborator

@pabigot pabigot left a 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;
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Member

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?

Copy link
Contributor Author

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.

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];
Copy link
Member

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)?

Comment on lines 548 to 551
/* perform shift in RAM */
if ((flash_prefix - dest_prefix) != 0) {
memmove(dptr + flash_prefix, dptr + dest_prefix, flash_middle);
}
Copy link
Member

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.

}

/* perform shift in RAM */
if ((flash_prefix - dest_prefix) != 0) {
Copy link
Member

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?

Comment on lines +78 to +80
if (!is_buf_clear) {
/* erase page */
rc = flash_erase(flash_dev, page_info.start_offset,
Copy link
Member

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).

Copy link
Contributor Author

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.

Comment on lines +92 to +94
rc = flash_write(flash_dev,
page_info.start_offset,
expected, EXPECTED_SIZE);
Copy link
Member

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?

@m-syc m-syc force-pushed the non_aligned_flash_read branch from 019dabd to eb33fab Compare July 20, 2020 08:52
uint8_t __aligned(WORD_SIZE) buf[WORD_SIZE * 2];
uint8_t *dptr = dest;

off_t flash_prefix = WORD_SIZE - (addr % WORD_SIZE) % WORD_SIZE;
Copy link
Member

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.

Suggested change
off_t flash_prefix = WORD_SIZE - (addr % WORD_SIZE) % WORD_SIZE;
off_t flash_prefix = (WORD_SIZE - (addr % WORD_SIZE)) % WORD_SIZE;

Mateusz Syc added 2 commits July 20, 2020 11:25
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>
@m-syc m-syc force-pushed the non_aligned_flash_read branch from eb33fab to 1d06546 Compare July 20, 2020 09:28
@carlescufi carlescufi merged commit 47bb6a3 into zephyrproject-rtos:master Jul 20, 2020
@m-syc m-syc deleted the non_aligned_flash_read branch July 20, 2020 11:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Drivers area: Flash area: QSPI Quad SPI area: Tests Issues related to a particular existing or missing test platform: nRF Nordic nRFx
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants