Chapter 61. The legacy Version 1 eCos FLASH API

The library has a number of limitations:

  1. Only one family of FLASH device may be supported at once.

  2. Multiple devices of one family are supported, but they must be contiguous in memory.

  3. The library is not thread or interrupt safe under some conditions.

  4. The library currently does not use the eCos naming convention for its functions. This may change in the future but backward compatibility is likely to be kept.

There are two APIs described here. The first is the application API which programs should use. The second API is that between the FLASH io library and the device drivers.

FLASH user API

All of the functions described below are declared in the header file <cyg/io/flash.h> which all users of the FLASH library should include.

Initializing the FLASH library

The FLASH library needs to be initialized before other FLASH operations can be performed. This only needs to be done once. The following function will only do the initialization once so it's safe to call multiple times:

externC int flash_init( _printf *pf ); 
typedef int _printf(const char *fmt, ...); 

The parameter pf is a pointer to a function which is to be used for diagnostic output. Typically the function diag_printf() will be passed. Normally this function is not used by the higher layer of the library unless CYGSEM_IO_FLASH_CHATTER is enabled. Passing a NULL is not recommended, even when CYGSEM_IO_FLASH_CHATTER is disabled. The lower layers of the library may unconditionally call this function, especially when errors occur, probably resulting in a more serious error/crash!.

Retrieving information about the FLASH

The following four functions return information about the FLASH.

externC int flash_get_block_info(int *block_size, int *blocks);
externC int flash_get_limits(void *target, void **start, void **end);
externC int flash_verify_addr(void *target);
externC bool flash_code_overlaps(void *start, void *end);

The function flash_get_block_info() returns the size and number of blocks. When the device has a mixture of block sizes, the size of the "normal" block will be returned. Please read the source code to determine exactly what this means. flash_get_limits() returns the lower and upper memory address the FLASH occupies (NOTE: For the upper memory address this is the last valid FLASH location, and not the first memory address after the FLASH). The target parameter is currently unused. flash_verify_addr() tests if the target addresses is within the flash, returning FLASH_ERR_OK if so. Lastly, flash_code_overlaps() checks if the executing code is resident in the section of flash indicated by start and end. If this function returns true, erase and program operations within this range are very likely to cause the target to crash and burn horribly. Note the FLASH library does allow you to shoot yourself in the foot in this way.

Reading from FLASH

There are two methods for reading from FLASH. The first is to use the following function.

externC int flash_read(void *flash_base, void *ram_base, int len, void **err_address);

flash_base is where in the flash to read from. ram_base indicates where the data read from flash should be placed into RAM. len is the number of bytes to be read from the FLASH and err_address is used to return the location in FLASH that any error occurred while reading.

The second method is to simply memcpy() directly from the FLASH. This is not recommended since some types of device cannot be read in this way, eg NAND FLASH. Using the FLASH library function to read the FLASH will always work so making it easy to port code from one FLASH device to another.

Erasing areas of FLASH

Blocks of FLASH can be erased using the following function:

externC int flash_erase(void *flash_base, int len, void **err_address);

flash_base is where in the flash to erase from. len is the minimum number of bytes to erase in the FLASH and err_address is used to return the location in FLASH that any error occurred while erasing. It should be noted that FLASH devices are block oriented when erasing. It is not possible to erase a few bytes within a block, the whole block will be erased. flash_base may be anywhere within the first block to be erased and flash_base+len may be anywhere in the last block to be erased.

Programming the FLASH

Programming of the flash is achieved using the following function.

externC int flash_program(void *flash_base, void *ram_base, int len, void **err_address);

flash_base is where in the flash to program from. ram_base indicates where the data to be programmed into FLASH should be read from in RAM. len is the number of bytes to be program into the FLASH and err_address is used to return the location in FLASH that any error occurred while programming.

Locking and unlocking blocks

Some flash devices have the ability to lock and unlock blocks. A locked block cannot be erased or programmed without it first being unlocked. For devices which support this feature and when CYGHWR_IO_FLASH_BLOCK_LOCKING is enabled then the following two functions are available:

externC int flash_lock(void *flash_base, int len, void **err_address);
externC int flash_unlock(void *flash_base, int len, void **err_address);

Return values and errors

All the functions above, except flash_code_overlaps() return one of the following return values.

FLASH_ERR_OK              No error - operation complete
FLASH_ERR_INVALID         Invalid FLASH address
FLASH_ERR_ERASE           Error trying to erase
FLASH_ERR_LOCK            Error trying to lock/unlock
FLASH_ERR_PROGRAM         Error trying to program
FLASH_ERR_PROTOCOL        Generic error
FLASH_ERR_PROTECT         Device/region is write-protected
FLASH_ERR_NOT_INIT        FLASH info not yet initialized
FLASH_ERR_HWR             Hardware (configuration?) problem
FLASH_ERR_ERASE_SUSPEND   Device is in erase suspend mode
FLASH_ERR_PROGRAM_SUSPEND Device is in program suspend mode
FLASH_ERR_DRV_VERIFY      Driver failed to verify data
FLASH_ERR_DRV_TIMEOUT     Driver timed out waiting for device
FLASH_ERR_DRV_WRONG_PART  Driver does not support device
FLASH_ERR_LOW_VOLTAGE     Not enough juice to complete job

To turn an error code into a human readable string the following function can be used:

externC char *flash_errmsg(int err);

Notes on using the FLASH library

The FLASH library evolved from the needs and environment of RedBoot rather than being a general purpose eCos component. This history explains some of the problems with the library.

The library is not thread safe. Multiple simultaneous calls to its library functions will likely fail and may cause a crash. It is the callers responsibility to use the necessary mutex's if needed.

2017-02-09
Documentation license for this page: Open Publication License