Skip to content

mtd flash: add a generic low level flash interface [RFC]#5624

Merged
vincent-d merged 5 commits intoRIOT-OS:masterfrom
OTAkeys:pr/mtdi_flash
Mar 17, 2017
Merged

mtd flash: add a generic low level flash interface [RFC]#5624
vincent-d merged 5 commits intoRIOT-OS:masterfrom
OTAkeys:pr/mtdi_flash

Conversation

@vincent-d
Copy link
Member

This PR adds a low level flash interface and a basic dummy flash implementation for the native cpu.

Comments are welcomed.

@LudwigKnuepfer
Copy link
Member

Please compare with #2239 and fuse the efforts.

@OlegHahm OlegHahm added the Discussion: RFC The issue/PR is used as a discussion starting point about the item of the issue/PR label Jul 12, 2016
@LudwigKnuepfer
Copy link
Member

LudwigKnuepfer commented Jul 12, 2016

OK, I'm refraining from code review until #5624 (comment) is addressed.

@vincent-d vincent-d mentioned this pull request Jul 13, 2016
55 tasks
@jnohlgard jnohlgard added Type: new feature The issue requests / The PR implemements a new feature for RIOT Area: drivers Area: Device drivers labels Jul 13, 2016
*/
typedef enum {
MTDI_STA_INIT = 0x00, /**< Drive initialized */
MTDI_STA_NOINIT = 0x01, /**< Drive not initialized */
Copy link
Member

@jnohlgard jnohlgard Jul 14, 2016

Choose a reason for hiding this comment

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

IMO it's better to have noinit = 0, because then the initial value will be set to "not initialized" on boot even if placed in .bss

@jnohlgard
Copy link
Member

The native MTD emulation device needs to do some bounds checking on the addresses and sizes to avoid writing outside the emulated memory. The fwrite will succeed and the file will grow, but that won't work when you move it to a real MTD.

Some introductory documentation is needed to explain what is meant by a page and a sector and what the alignment requirements are for the different functions.

Are writes to already written sectors allowed? native MTD emulation should emulate flash by only programming the 0 bits (value = value & input).

@jnohlgard
Copy link
Member

@LudwigKnuepfer I like the proposed structure with a driver struct containing pointers to all the functions to allow more than one type of flash device present in the same running system, this was difficult to achieve with the interface proposed in #2239. The interface proposed in this PR is similar to the already existing NVRAM interface.

@jnohlgard
Copy link
Member

jnohlgard commented Jul 14, 2016

@LudwigKnuepfer though I agree that there are many good parts in #2239 that could be lifted into this PR. For example the native flash emulation in #2239 emulate the properties of flash better than the current state of this PR does.

if (addr + size > NATIVE_MTDI_FLASH_SIZE) {
return MTDI_RES_PARERR;
}
if (addr % NATIVE_MTDI_SECTOR_SIZE + size > NATIVE_MTDI_SECTOR_SIZE) {
Copy link
Member

Choose a reason for hiding this comment

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

add some parentheses to make this a bit more readable

Copy link
Member Author

Choose a reason for hiding this comment

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

addressed

@vincent-d
Copy link
Member Author

Doc improved, even if it could still be better. Still not entirely sure about the boundaries for read/write/erase, but it seems to match at least how SPIFFS uses it.

I also improved the flash emulation.

if (addr + size > NATIVE_MTDI_FLASH_SIZE) {
return MTDI_RES_PARERR;
}
if (addr % NATIVE_MTDI_SECTOR_SIZE != 0 || size % NATIVE_MTDI_SECTOR_SIZE != 0) {
Copy link
Member

Choose a reason for hiding this comment

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

parens

Copy link
Member Author

Choose a reason for hiding this comment

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

addressed

@jnohlgard
Copy link
Member

btw, why is it called MTDI and not just MTD?

@vincent-d
Copy link
Member Author

The I stands for interface. @AurelienGONCE wanted to clearly show that it's an interface ;)
I have no better explanation!
It can still renamed, that is no big deal for me.

#define ENABLE_DEBUG (0)
#include "debug.h"

static const char _fname[] = "MEMORY.bin";
Copy link
Member

@LudwigKnuepfer LudwigKnuepfer Jul 14, 2016

Choose a reason for hiding this comment

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

I would like to see this provided as a command line parameter or option.

@jnohlgard
Copy link
Member

jnohlgard commented Jul 14, 2016

I'd prefer to call the interface MTD and the main interface file mtd.h, then the implementations can be called mtd_native.h, mtd_spi.h etc.

btw, I'm working on a SPI NOR flash driver for this interface.

* The number of pages in a sector must be constant for the whole MTD.
*
* Most of the flash filesystems implementation will use pages as basic unit for writing.
* This interface does not limit the writing on bage boundaries but user must not write on
Copy link
Member

Choose a reason for hiding this comment

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

"bage" -> "page"

@jnohlgard
Copy link
Member

What is the use case for the mtdi_status function?

@jnohlgard
Copy link
Member

Some more review comments:

The argument types for buffers unsigned char * should be changed to void * according to the coding conventions:
https://github.com/RIOT-OS/RIOT/wiki/Coding-conventions
See also a recent discussion on the mailing list: https://lists.riot-os.org/pipermail/devel/2016-July/004155.html

I suggest that the addr and size parameters change to uint32_t to make it more visible what the supported memory address space is.

We tend to avoid "getter" functions for simple values in RIOT. I suggest that the GET_xxx stuff in ioctl be moved to public variables inside the device instance struct mtdi_dev_t. Since the documentation also states that an MTD consists of sectors and pages, these counts and sizes could just go directly in mtdi_dev_t.

typedef struct {
    const mtdi_desc_t *driver;
    uint32_t sector_count;
    uint32_t pages_per_sector;
    uint32_t page_size;
} mtdi_dev_t;

The other numbers can be derived from those three values by multiplication. Also, it avoids a possible ambiguity regarding total memory size by eliminating the redundant counts.

@vincent-d
Copy link
Member Author

Fix doxygen and cppcheck errors

@vincent-d vincent-d added the CI: needs squashing Commits in this PR need to be squashed; If set, CI systems will mark this PR as unmergable label Mar 10, 2017
TEST_ASSERT_EQUAL_INT(0, memcmp(buf_empty, buf_read + sizeof(buf), sizeof(buf_empty)));

/* Unaligned write / read */
ret = mtd_write(dev, buf, dev->page_size, sizeof(buf));
Copy link
Member

Choose a reason for hiding this comment

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

How about we change this to

ret = mtd_write(dev, buf, dev->page_size + sizeof(buf_empty), sizeof(buf));

and change the readback to match:

TEST_ASSERT_EQUAL_INT(0, memcmp(buf_empty, buf_read, sizeof(buf_empty)));
TEST_ASSERT_EQUAL_INT(0, memcmp(buf, buf_read + sizeof(buf_empty), sizeof(buf)));

that will test completely unaligned writes, and also catch implementation errors where the read or write addresses are not the same

Copy link
Member Author

Choose a reason for hiding this comment

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

good idea, done

@jnohlgard
Copy link
Member

It looks okay now, I'll give it a spin later tonight or tomorrow and give my ACK.

@jnohlgard
Copy link
Member

Ok to squash

if (!f) {
return -EIO;
}
unsigned long size = dev->sector_count * dev->pages_per_sector * dev->page_size;
Copy link
Contributor

Choose a reason for hiding this comment

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

how about size_t?

Copy link
Member Author

Choose a reason for hiding this comment

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

It could make sense. I'll change that here and in other places.

@jnohlgard
Copy link
Member

found one minor nit in mtd_vfs. I'm writing a unittest for mtd_vfs too. I'll post back when it's done

@vincent-d
Copy link
Member Author

Squashed, with @kaspar030 remark fixed

@vincent-d vincent-d removed the CI: needs squashing Commits in this PR need to be squashed; If set, CI systems will mark this PR as unmergable label Mar 16, 2017
@jnohlgard
Copy link
Member

jnohlgard commented Mar 16, 2017

Two commits for mtd-vfs:
OTAkeys@ee8cf6e
OTAkeys@c3dbf38

@vincent-d
Copy link
Member Author

@gebart cherry-picked and squashed, thanks

@vincent-d
Copy link
Member Author

I don't understand why Murdock2 failed. Murdock and Jenkins seem happy anyway.

@vincent-d
Copy link
Member Author

@gebart thanks! Shall I press the button ?

@jnohlgard
Copy link
Member

ACK,
@vincent-d would you like the honor of pressing the button?

@vincent-d
Copy link
Member Author

Then GO!
Thanks @gebart !

@vincent-d vincent-d merged commit 1b2b5d9 into RIOT-OS:master Mar 17, 2017
@vincent-d vincent-d deleted the pr/mtdi_flash branch March 17, 2017 16:18
@jnohlgard
Copy link
Member

Congratulations 🎊 🎉
Now, let's get the mtd_spi_nor stuff merged

@kYc0o kYc0o mentioned this pull request Mar 21, 2017
@jnohlgard jnohlgard added the Area: fs Area: File systems label Feb 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area: drivers Area: Device drivers Area: fs Area: File systems CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Community: Hack'n'ACK candidate This PR is a candidate for review and discussion during one of RIOT's monthly Hack'n'ACK parties Discussion: RFC The issue/PR is used as a discussion starting point about the item of the issue/PR Type: new feature The issue requests / The PR implemements a new feature for RIOT

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants