eCos Product
eCos Net Distribution
RedBoot Product
RedBoot Net Distribution
Supported Hardware
Downloading and Installation
Documentation
FAQ
Keeping in Touch
Problems
Licensing
Anonymous CVS
Contributions and Third Party Projects
|
Flash Driver
A flash device driver consists of two elements: a generic device
driver which knows how to handle a particular part or family of flash
devices, and a platform specific driver which contains information
about how the devices are laid out on the particular platform. This
allows the core device driver to be shared by multiple platforms which
have different device configurations.
The below descriptions are based on the AMD
AM29xxxxx generic driver and the PowerPC
MBX platform driver.
Other device drivers (e.g. ethernet drivers) rely on the platform
driver to provide a header file with details which is included when
the generic driver object is built. But in the flash device drivers,
the generic driver is provided as an .inl header file which
is included when the driver object is built in the platform
driver.
The reason for this is that the driver code needs compile-time
configuration to handle different configurations of interleaved
devices. Letting the platform driver build the object allows the same
generic driver to be used in multiple different configurations on the
same platform.
General Issues
Error values
Error values are defined in the IO flash driver. For the
current list of errors, see the file flash.h. Here's
the list at the time of writing:
#define FLASH_ERR_OK 0x00 // No error - operation complete
#define FLASH_ERR_INVALID 0x01 // Invalid FLASH address
#define FLASH_ERR_ERASE 0x02 // Error trying to erase
#define FLASH_ERR_LOCK 0x03 // Error trying to lock/unlock
#define FLASH_ERR_PROGRAM 0x04 // Error trying to program
#define FLASH_ERR_PROTOCOL 0x05 // Generic error
#define FLASH_ERR_PROTECT 0x06 // Device/region is write-protected
#define FLASH_ERR_NOT_INIT 0x07 // FLASH info not yet initialized
#define FLASH_ERR_HWR 0x08 // Hardware (configuration?) problem
#define FLASH_ERR_ERASE_SUSPEND 0x09 // Device is in erase suspend mode
#define FLASH_ERR_PROGRAM_SUSPEND 0x0a // Device is in in program suspend mode
#define FLASH_ERR_DRV_VERIFY 0x0b // Driver failed to verify data
#define FLASH_ERR_DRV_TIMEOUT 0x0c // Driver timed out waiting for device
#define FLASH_ERR_DRV_WRONG_PART 0x0d // Driver does not support device
#define FLASH_ERR_LOW_VOLTAGE 0x0e // Not enough juice to complete job
Void pointers
Different drivers will have different word widths, depending
on device types and number of interleaved devices. Since the IO
driver must be able to use them all, device and data addresses are
passed as void pointers, and size arguments always denote
bytes.
Flash interleaving
Different platforms may use the same flash parts in different
interleaved configurations, e.g., platform A has one 16-bit device,
while platform B has two interleaved (parallel) devices to create one
virtual 32-bit wide device. For this reason, all access to the device
is done using the flash_data_t type which takes on the
correct width, and all device commands are defined to the correct
width using the macro FLASHWORD. -
Flash mapping
On some platforms the flash devices may not be linearly
accessible. In order to let the driver work on such platforms, all
addressing of the device should use the FLASH_P2V macro
which does a physical address translation to a virtual address which
works with the device on the particular platform.
Flash access
All access operations that take the flash device out of its
normal random access data mode must be done from RAM. Therefore all
such functions must be put in the special .2ram section
which will get copied to RAM during system initialization.
Caching during access
Some architectures/platforms will access the flash area in
burst mode, which spoils the flash interaction protocols. To counter
this, the IO driver disables caches before calling the driver
functions. This is done using the macro HAL_FLASH_CACHES_OFF
and the matching HAL_FLASH_CACHES_ON for which there are
generic definitions in the IO driver. Some architectures/platforms may
have to override these macros though.
Generic Flash Driver
The generic driver package must contain CDL in the following
style:
cdl_package CYGPKG_DEVS_FLASH_AMD_AM29XXXXX {
display "AMD AM29XXXXX FLASH memory support"
description "FLASH memory device support for AMD AM29XXXXX"
parent CYGPKG_IO_FLASH
active_if CYGPKG_IO_FLASH
active_if CYGINT_DEVS_FLASH_AMD_AM29XXXXX_REQUIRED
implements CYGHWR_IO_FLASH_DEVICE
include_dir cyg/io
}
The package is only enabled if the IO flash driver is present and
CYGINT_DEVS_FLASH_AMD_AM29XXXXX_REQUIRED is defined in the
platform flash driver. There are no files to build, since the driver
is provided in the form of an .inl header file.
The flash driver must provide the API described below. Note that this
API is likely to change some time in the future to allow multiple
flash drivers in the same system.
- int flash_hwr_init(void)
Ensures that the device is indeed a supported device by
querying the manufacturer and/or type codes. Also initializes flash
driver data with flash size, location, number of regions and region
sizes.
- void flash_query(void* data)
Reads whatever information is needed from the flash device
necessary to identify it. This is usually the manufacturer and part
numbers which are written to data. This function should only
be called from within the driver (which knows the size of the data
stored). The function is only public because it needs to be called
via the IO driver.
- int flash_hwr_map_error(int err)
Translates a flash error code to an eCos flash error
code. This is a null operation (legacy function) since the driver
should always return eCos flash error codes anyway.
- bool flash_code_overlaps(void *start, void *end)
Determines if the specified flash range overlaps with any
running code, thus allowing an abort of the operation. FIXME: This
function should be removed from the device driver.
- int flash_erase_block(volatile void* block)
Erase the specified block. Returns FLASH_ERR_OK if the
operation succeeded, otherwise an error code describing the
failure.
- int flash_program_buf(volatile void* addr, void* data,
int len)
Program the flash starting at addr with the data
pointed to by data. len specifies number of bytes
to program. Returns FLASH_ERR_OK if the operation succeeded,
otherwise an error code describing the failure.
Some drivers may also include functionality to lock and unlock
areas of the flash device. In that case, the CDL must include a
implements CYGHWR_IO_FLASH_BLOCK_LOCKING statement. [FIXME:
These functions do not have a consistent interface yet -- or is there
a reason for one taking a single block and the other a range?]
- int flash_lock_block(volatile void* block)
Locks the block specified. Returns FLASH_ERR_OK if the
operation succeeded, otherwise an error code describing the
failure.
- int flash_unlock_block(volatile void* block,
int block_size, int blocks)
Unlocks specified range of blocks. Returns FLASH_ERR_OK if the
operation succeeded, otherwise an error code describing the
failure.
Platform Specific Driver
The platform driver package must contain CDL in the following
style:
cdl_package CYGPKG_DEVS_FLASH_MBX {
display "Motorola PowerPC/860 FLASH memory support"
parent CYGPKG_IO_FLASH
active_if CYGPKG_IO_FLASH
requires CYGPKG_HAL_POWERPC_MBX
implements CYGHWR_IO_FLASH_DEVICE
compile powerpc_mbx_flash.c
# Arguably this should do in the generic package
# but then there is a logic loop so you can never enable it.
cdl_interface CYGINT_DEVS_FLASH_AMD_AM29XXXXX_REQUIRED {
display "Generic AMD AM29F040 driver required"
}
implements CYGINT_DEVS_FLASH_AMD_AM29XXXXX_REQUIRED
requires CYGHWR_DEVS_FLASH_AMD_AM29F040B
}
It enables the generic driver by providing the interface option,
and by the requires statement ensures that the driver includes the
necessary device support. The compile statement identifies
the file which, when built, includes the generic driver code.
The platform driver file itself is quite simple, as all it has to
do is specify device parameters and include the generic driver:
//--------------------------------------------------------------------------
// Device properties
// We use the single AM29F040B on the MBX board.
#define CYGNUM_FLASH_INTERLEAVE (1)
#define CYGNUM_FLASH_SERIES (1)
#define CYGNUM_FLASH_WIDTH (8)
#define CYGNUM_FLASH_BASE (0xfe000000u)
//--------------------------------------------------------------------------
// Platform specific extras
//--------------------------------------------------------------------------
// Now include the driver code.
#include "cyg/io/flash_am29xxxxx.inl"
The definitions have the following meaning:
- CYGNUM_FLASH_INTERLEAVE
Defines how many devices are interleaved (sits in parallel)
for this region of flash. The flash_data_t supports various
configurations up to a max width of 64 bits.
- CYGNUM_FLASH_SERIES
Defines how many number of devices are in series. The total
number of devices is then defined as
(CYGNUM_FLASH_INTERLEAVE x
CYGNUM_FLASH_SERIES).
- CYGNUM_FLASH_WIDTH
Defines the width of the devices. Some devices support being
used in more than one width configuration (i.e., some 16 bit wide
devices can be configured to only use the 8 lowest data
bits).
- CYGNUM_FLASH_BASE
Defines the address base of the flash region.
|