Name
CYGPKG_DEVS_FLASH_M68K_MCFxxxx_CFM — eCos Flash Driver for MCFxxxx CFM On-chip Flash
Description
Some members of the Freescale MCFxxxx family, for example the MCF5213,
come with on-chip flash in the form of a ColdFire Flash Module or CFM.
This package CYGPKG_DEVS_FLASH_M68K_MCFxxxx_CFM
provides an eCos flash device driver for CFM hardware. Normally the
driver is not accessed directly. Instead application code will use the
API provided by the generic flash driver package
CYGPKG_IO_FLASH
, for example by calling functions
like cyg_flash_program
.
Configuration Options
The CFM flash driver package will be loaded automatically when
configuring eCos for a target with suitable hardware. However the
driver will be inactive unless the generic flash package
CYGPKG_IO_FLASH
is loaded. It may be necesary to
add this generic package to the configuration explicitly before the
driver functionality becomes available. There should never be any need
to load or unload the CFM driver package.
The driver contains a small number of configuration options which application developers may wish to tweak.
Misaligned Writes
The CFM hardware only supports writes of a whole 32-bit integer at a
time. For most applications this is not a problem and the driver
imposes this restriction on higher-level code, so when calling
cyg_flash_program
the destination address must be
on a 32-bit boundary and the length must be a multiple of four bytes.
If this restriction is unacceptable then support for misaligned writes
of arbitrary lengths can be enabled via configuration option
CYGIMP_DEVS_FLASH_M68K_MCFxxxx_CFM_MISALIGNED_WRITES
.
The implementation involves reading in the existing flash contents and
or'ing in the new data. The default behaviour is to leave this
disabled since most applications do not require the functionality and
it just adds to the code size.
Locking
CFM has a somewhat unusual approach to implementing lock and unlock
support. The first 1K of on-chip flash is normally reserved for the
M68K exception vectors, on the assumption that the processor will or
may boot from here. This is immediately followed by a
hal_mcfxxxx_cfm_security_settings data
structure at offset 0x400. The structure has a 32-bit field
cfm_prot
which determines the initial
locking status. The whole CFM flash array is split into 32 sectors.
Each bit in cfm_prot
determines the initial
locked state of all blocks within that sector, with 1 for locked and 0
for unlocked. Locking and unlocking can only affect a whole sector at
a time, not individual flash blocks (unless of course the flash is
organized such that there exactly 32 flash blocks).
In typical usage the on-chip flash will be used for bootstrap and hence the security settings are part of the boot image. The default security settings are supplied by the processor or platform HAL and will be such that all flash sectors are unlocked. This is the most convenient setting when developing software. However an application can override this and thus lock part or all of the flash.
The driver provides two configuration options related to flash
locking.
CYGIMP_DEVS_FLASH_M68K_MCFxxxx_CFM_AUTO_UNLOCK
causes all of flash to be unlocked automatically during driver
initialization. This gives simple and deterministic behaviour
irrespective of the current contents of the flash security settings
structure. However it leaves the flash more vulnerable to accidental
corruption by an errant application.
CYGIMP_DEVS_FLASH_M68K_MCFxxxx_CFM_SUPPORT_LOCKING
enables support for fine-grained locking using the generic functions
cyg_flash_lock
and
cyg_flash_unlock
. This provides more protection
against errant applications, at the cost of increased application
complexity.
RAM Functions and Interrupts
When performing a flash erase or program operation part or all of the flash may become inaccessible. The exact details of this vary between ColdFire processors. Obviously this means that the low-level functions which manipulate the flash cannot reside in the same area of flash as any blocks that may get erased or programmed. Worse, if an interrupt happens during an erase or program operation and the interrupt handler involves code or data in the same area of flash, or may cause a higher priority thread to wake up which accesses that area of flash, then the system is likely to fail. To avoid problems the flash driver takes two precautions by default:
- The low-level flash functions are located in RAM. If necessary they are copied from ROM from RAM during system initialization.
- The low-level flash functions disable interrupts around any code which may leave parts of the flash inaccessible.
This combination avoids problems but at the cost of increased RAM
usage and often increased interrupt latency. In some circumstances
these precautions are unnecessary. For example suppose there is 512K
of flash split into two logical blocks of 256K each, such that an
erase or program operation affects all of one logical block but not
the other. If the application has been arranged such that all code and
constant data resides in the bottom 256K and flash operations are only
performed on the remaining 256K then there is no need to place the
low-level flash functions in RAM. The configuration option
CYGIMP_DEVS_FLASH_M68K_MCFxxxx_CFM_FUNCTIONS_IN_RAM
can then be disabled. In a similar scenario, if the top 256K of flash
are only ever accessed via the flash API then there is no need to
disable interrupts: the generic flash layer ensures only one thread
can perform flash operations on a given device via a mutex. The
configuration option
CYGIMP_DEVS_FLASH_M68K_MCFxxxx_CFM_LEAVE_INTERRUPTS_ENABLED
can then be enabled.
Additional Functionality
The driver exports two functions which offer functionality not accessible via the standard flash API:
#include <cyg/io/mcfxxxx_cfm_dev.h> externC void cyg_mcfxxxx_cfm_unlockall(void); externC cyg_bool cyg_mcfxxxx_cfm_is_locked(const cyg_flashaddr_t addr);
The first can be used to unlock all flash sectors, effectively bypassing any locking set by the hal_mcfxxxx_cfm_security_settings structure. The second can be used to query whether or not the block containing the specified address is currently locked. Both functions should be called only after flash has been initialized.
Instantiating a CFM Flash device
The CFM package only provides the device driver functions needed for manipulating CFM flash. It does not actually create a device instance. The amount of on-chip flash varies between ColdFire processors and the driver package does not maintain any central repository about the characteristics of each processor. Instead it is left to other code, usually the processor HAL, to instantiate the flash device. That makes it possible to add support for new processors simply by adding a new processor HAL, with no need to change the flash driver package.
The CFM package provides a utility macro for instantiating a device. Typical usage would be:
#include <cyg/io/mcfxxxx_cfm_dev.h> CYG_MCFxxxx_CFM_INSTANCE(0x00000000, 0x0003FFFF, 2048);
The first two arguments specify the base and end address of the flash in the memory map. In this example there is 256K of flash mapped to location 0. Typically the base address is set via the FLASHBAR system register and the size is of course determined by the specific ColdFire processor being used. The final argument is the size of a flash block, in other words the unit of erase operations. This will have to obtained from the processor documentation.
The CYG_MCFxxxx_CFM_INSTANCE
macro may
instantiate a device with or without software locking support, as
determined by the driver configuration option
CYGIMP_DEVS_FLASH_M68K_MCFxxxx_CFM_SUPPORT_LOCKING
.
If for some reason the CYG_MCFxxxx_CFM_INSTANCE
is inappropriate for a specific processor then the mcfxxxx_cfm_dev.h
header file exports all the device driver functions, so code can
create a flash device instance explicitly.
2024-12-10 | eCosPro Non-Commercial Public License |