This technote explains how to choose the correct Memory Technology Driver (MTD) routine for your flash filesystem. Before you begin, you should first review the descriptions of all available MTD callouts for a flash driver. See "Building your flash filesystem driver" in the Customizing the Flash Filesystem chapter of Building Embedded Systems.
The MTD callouts are as follows:
| Callout | Description |
|---|---|
| ident() | Identify the flash chip(s) |
| reset() | Return the flash to the read state after an error |
| read() | Read data from flash (if NULL, an internal memcpy() is used) |
| write() | Write data to flash |
| erase() | Erase a flash block (also known as a "unit") |
| sync() | Poll for the completion of an erasure |
| suspend() | Suspend an erasure for a read/write operation (if supported) |
| resume() | Resume a suspended erasure after a read/write operation (if supported) |
| islock() | Determine whether a block/unit is write protected |
| lock() | Write-protect a block |
| unlock() | Disable write protection |
| unlockall() | Invoke a single command to unlock the whole chip (if supported) |
| Generic callout | MTDv1 | MTDv2 |
|---|---|---|
| ident() | f3s_ident() | f3s_ident() |
| reset() | f3s_reset() | f3s_reset() |
| read() | f3s_read() | f3s_v2read() |
| write() | f3s_write() | f3s_v2write() |
| erase() | f3s_erase() | f3s_v2erase() |
| sync() | f3s_sync() | f3s_v2sync() |
| suspend() | f3s_suspend() | f3s_v2suspend() |
| resume() | f3s_resume() | f3s_v2resume() |
| islock() | — | f3s_v2islock() |
| lock() | — | f3s_v2lock() |
| unlock() | — | f3s_v2unlock() |
| unlockall() | — | f3s_v2unlockall() |
Ideally, there would be a table that describes every combination of board and flash in existence and tells you which callout to use. Since this is unrealistic, this technote focuses mainly on describing a general method for choosing the right combination of MTD callouts. You will need to:
As a first step, you should determine whether your board has an unusual flash configuration. In a standard flash configuration, the flash should be located at a contiguous physical memory address that can be directly mapped, read, and written to by software. Usually, the chips are allowed to be interleaved for performance/bus-width reasons.
Here are some examples of nonstandard flash configurations:
If your board has any such unusual configuration, don't hesitate to consult your QNX Software Systems representative.
You can find the complete source to the MTD driver library under bsp_root/libs/src/hardware/flash/mtd-flash.
The callouts are grouped by manufacturer (e.g., intel/iCFI_write.c). Each of these files contains enough comments to detail the type of flash they work with. These comment-blocks provide the most up-to-date information on selecting the right MTD callout. Don't be afraid to look at these files.
Since the MTD source code is organized by manufacturer, your next step is to determine the manufacturer. Look at the board itself or read the flash's datasheet. Flash components made by different manufacturers are usually not compatible with each other.
There are also groups for SRAM and ROM; in this case there's only one choice for each callout, so we won't discuss them here.
Here's an example:
#include <sys/f3s_mtd.h>
int32_t f3s_mtd_read(f3s_dbase_t *dbase,
f3s_access_t *access,
uint32_t flags,
uint32_t offset,
int32_t size,
uint8_t *buffer)
{
uint8_t *memory;
/* Set proper page on socket */
memory = (uint8_t *)access->service->page(&access->socket,
F3S_POWER_ALL,
offset,
NULL);
if (memory == NULL)
{
fprintf(stderr,
"%s: %d page() returns NULL\n",
__func__,
__LINE__);
return (-1);
}
/* Replace this memcpy with your special handling code */
memcpy(buffer, memory, size);
return (size);
}
When consulting AMD's datasheets, don't confuse their "Unlock Bypass" write mode with their buffered write mode. The unlock bypass mode eliminates only the extra handshake between each word write. Real buffered write modes collect several words into an internal buffer and programs them in parallel.
If you need to use a f3s_v2sync() callout, there's usually only one to choose from.
The f3s_v2sync() callout doesn't need to know the erase block size. The size is determined by the filesystem via a different API.