Instantiating — including the driver in an eCos target


#include <cyg/io/dataflash.h>

CYG_DATAFLASH_FLASH_DRIVER (char *name, cyg_spi_device *sdev, cyg_uint32 addr, cyg_uint32 start, cyg_uint32 end);


The DataFlash family contains several different flash devices, all supporting the same basic set of operations The devices vary in capacity, performance and sector layout. There are also platform-specific issues such as which SPI bus the device is connected to, and which chip select it uses. The DataFlash driver package cannot know all this information. Instead it is the responsibility of another package, either the platform HAL or a flash configuration package, to instantiate some DataFlash device structures.

The definition of the parameters is split between two data structures. The first is an SPI specific data structure describing the SPI bus, chip select and signalling characteristics for the device. This is usually defined in an SPI specific configuration package or the platform HAL. The reader is referred to the SPI documentation for details of the contents of this structure, but see later for an example.

The second data structure defines the characteristics of the DataFlash device for use by the flash subsystem. For convenience a macro, CYG_DATAFLASH_FLASH_DRIVER, has been defined to automate the generation of this structure. This macro takes a number of arguments:

This provides a name fragment for distinguishing this DataFlash device from any others. It is concatenated with cyg_dataflash_priv_ to form a static variable name. Any unique string that obeys the rules of C variable names is sufficient.
A pointer to the SPI device object that describes this flash device. If the SPI device has been declared with the name spi_dataflash_dev0 then this argument should be (&spi_dataflash_dev0.spi_device).
SPI DataFlash devices do not have a physical address in the system memory space. However, the flash subsystem expects all flash devices to have an address. This argument gives the DataFlash device a virtual address in the memory space. This should be allocated to a location that contains no other flash devices, and to avoid confusion, no other memory or devices. Subsequently, the DataFlash may be accessed by performing flash system accesses starting at this address.
This parameter defines the sector at which the flash device mapping starts. The beginning of this sector is mapped to the virtual address given in the addr argument. This value will usually be zero, but may be non-zero if there is reserved data at the beginning of the DataFlash.
This parameter defines the sector at which the flash device mapping ends. The end of this sector defines the maximum extent in the address space that the DataFlash occupies. The exact size of the mapping will depend on the number and sizes of the flash sectors covered. This value will usually be the number of sectors in the device, but may be less if there is reserved data at the end of the DataFlash.


DataFlash support is usually specific to each platform. Even if two platforms happen to use the same flash device there are likely to be differences such as the SPI bus, chip select and location in the address map. Hence there is little possibility of re-using the platform-specific code, and this code is generally placed in the platform HAL or in a separate platform specific package.

The code to declare a DataFlash device might appear as follows:

#include <cyg/io/spi.h>
#include <cyg/io/spi_at91.h>
#include <cyg/io/dataflash.h>

__externC cyg_spi_at91_device_t spi_dataflash_dev0;

                            16 );

Here, we are defining a dataflash device that is mapped to virtual address 0x08000000. The start and end sectors cover the entire flash device, 17 sectors. In addition to a DataFlash specific structure, this macro also creates a cyg_flash_dev structure which supplies the driver interface to the flash subsystem. The SPI device structure is defined elsewhere, in an SPI specific package, and has the following format:

#include <cyg/infra/cyg_type.h>
#include <cyg/io/spi.h>
#include <cyg/io/spi_at91.h>

// AT45DB321B DataFlash
cyg_spi_at91_device_t spi_dataflash_dev0 CYG_SPI_DEVICE_ON_BUS(0) =
    .spi_device.spi_bus = &cyg_spi_at91_bus.spi_bus,

    .dev_num     = 0,       // Device number
    .cl_pol      = 1,       // Clock polarity (0 or 1)
    .cl_pha      = 0,       // Clock phase (0 or 1)
    .cl_brate    = 8192000, // Clock baud rate
    .cs_up_udly  = 1,       // Delay in usec between CS up and transfer start
    .cs_dw_udly  = 1,       // Delay in usec between transfer end and CS down
    .tr_bt_udly  = 1        // Delay in usec between two transfers

The parameters here attach the device to the only SPI bus in the hardware, use chip select 0 to access it, and set the communication parameters for the clock polarity, phase, baud rate and delays.

Device Info

The exact DataFlash device attached to the SPI bus is discovered by the driver by querying it and matching the device ID against an internal table of supported devices. If a particular device is not currently supported, it must be added to the table in devs_flash_atmel_dataflash.c. A typical entry in this table appears as follows:

{   // AT45DB321B
    device_id:    0x0D,
    page_size:    528,
    page_count:   8192,
    baddr_bits:   10,
    block_size:   8,
    sector_sizes: {  1, 63, 64, 64, 64, 64, 64, 64,
                    64, 64, 64, 64, 64, 64, 64, 64, 64 },
    sector_count: 17

The fields of this structure are:

This defines the device ID returned as part of the status register. This is the field that is matched to select this DataFlash device.
This gives the size of pages in this flash device.
This gives the total number of pages in this device.
This gives the number of bits used in the SPI command address format for specifying a byte address within a page.
This gives the number of pages in a block.
This is an array giving the size, in blocks, of each sector of the DataFlash.
This gives the number of entries in the sector_sizes array.