This section contains definitions for supporting control
of the caches on the CPU.
These definitions are usually found in the header file
cyg/hal/hal_cache.h. This file may be defined in
the architecture, variant or platform HAL, depending on where the
caches are implemented for the target. Often there will be a generic
implementation of the cache control macros in the architecture HAL
with the ability to override or undefine them in the variant or
platform HAL. Even when the implementation of the cache macros is in
the architecture HAL, the cache dimensions will be defined in the
variant or platform HAL. As with other files, the variant or platform
specific definitions are usually found in
cyg/hal/var_cache.h and
cyg/hal/plf_cache.h respectively. These files
are include automatically by this header, so need not be included
explicitly.
There are versions of the macros defined here for both the Data and
Instruction caches. these are distinguished by the use of either
DCACHE or ICACHE in the macro
names. Some architectures have a unified cache, where both data and
instruction share the same cache. In these cases the control macros
use UCACHE and the DCACHE and
ICACHE macros will just be calls to the
UCACHE version. In the following descriptions,
XCACHE is used to stand for any of these. Where
there are issues specific to a particular cache, this will be
explained in the text.
There might be target specific restrictions on the use of some of the
macros which it is the user's responsibility to comply with. Such
restrictions are documented in the header file with the macro
definition.
Note that destructive cache macros should be used with caution.
Preceding a cache invalidation with a cache synchronization is not
safe in itself since an interrupt may happen after the synchronization
but before the invalidation. This might cause the state of dirty data
lines created during the interrupt to be lost.
Depending on the architecture's capabilities, it may be possible to
temporarily disable the cache while doing the synchronization and
invalidation which solves the problem (no new data would be cached
during an interrupt). Otherwise it is necessary to disable interrupts
while manipulating the cache which may take a long time.
Some platform HALs now support a pair of cache state query
macros: HAL_ICACHE_IS_ENABLED( x ) and
HAL_DCACHE_IS_ENABLED( x ) which set the argument
to true if the instruction or data cache is enabled,
respectively. Like most cache control macros, these are optional,
because the capabilities of different targets and boards can vary
considerably. Code which uses them, if it is to be considered
portable, should test for their existence first by means of
#ifdef. Be sure to include
<cyg/hal/hal_cache.h> in order to do this
test and (maybe) use the macros.
These macros define the size and dimensions of the Instruction
and Data caches.
HAL_XCACHE_SIZE
Defines the total size of the cache in bytes.
HAL_XCACHE_LINE_SIZE
Defines the cache line size in bytes.
HAL_XCACHE_WAYS
Defines the number of ways in each set and defines its level
of associativity. This would be 1 for a direct mapped
cache, 2 for a 2-way cache, 4 for 4-way and so on.
HAL_XCACHE_SETS
Defines the number of sets in the cache, and is calculated from
the previous values.
These macros affect the state of the entire cache, or a large part of
it.
HAL_XCACHE_ENABLE() and HAL_XCACHE_DISABLE()
Enable and disable the cache.
HAL_XCACHE_INVALIDATE_ALL()
Causes the entire contents of the cache to be invalidated.
Depending on the hardware, this may require the cache to be disabled
during the invalidation process. If so, the implementation must
use HAL_XCACHE_IS_ENABLED() to save and
restore the previous state.
Note: If this macro is called after
HAL_XCACHE_SYNC() with the intention of clearing
the cache (invalidating the cache after writing dirty data back to
memory), you must prevent interrupts from happening between the two
calls:
Since the operation may take a very long time, real-time
responsiveness could be affected, so only do this when it is
absolutely required and you know the delay will not interfere
with the operation of drivers or the application.
HAL_XCACHE_SYNC()
Causes the contents of the cache to be brought into synchronization
with the contents of memory. In some implementations this may be
equivalent to HAL_XCACHE_INVALIDATE_ALL().
HAL_XCACHE_BURST_SIZE()
Allows the size of cache to/from memory bursts to
be controlled. This macro will only be defined if this functionality
is available.
HAL_DCACHE_WRITE_MODE()
Controls the way in which data cache lines are written back to
memory. There will be definitions for the possible
modes. Typical definitions are
HAL_DCACHE_WRITEBACK_MODE and
HAL_DCACHE_WRITETHRU_MODE. This macro will
only be defined if this functionality is available.
HAL_XCACHE_LOCK()
Causes data to be locked into the cache. The base and size
arguments define the memory region that will be locked into the
cache. It is architecture dependent whether more than one locked
region is allowed at any one time, and whether this operation
causes the cache to cease acting as a cache for addresses
outside the region during the duration of the lock. This macro
will only be defined if this functionality is available.
HAL_XCACHE_UNLOCK()
Cancels the locking of the memory region given. This should
normally correspond to a region supplied in a matching lock
call. This macro will only be defined if this functionality is
available.
HAL_XCACHE_UNLOCK_ALL()
Cancels all existing locked memory regions. This may be required
as part of the cache initialization on some architectures. This
macro will only be defined if this functionality is available.
HAL_DCACHE_ALLOCATE( base , size )
HAL_DCACHE_FLUSH( base , size )
HAL_XCACHE_INVALIDATE( base , size )
HAL_DCACHE_STORE( base , size )
HAL_DCACHE_READ_HINT( base , size )
HAL_DCACHE_WRITE_HINT( base , size )
HAL_DCACHE_ZERO( base , size )
All of these macros apply a cache operation to all cache lines that
match the memory address region defined by the base and size
arguments. These macros will only be defined if the described
functionality is available. Also, it is not guaranteed that the cache
function will only be applied to just the described regions, in some
architectures it may be applied to the whole cache.
HAL_DCACHE_ALLOCATE()
Allocates lines in the cache for the given region without
reading their contents from memory, hence the contents of the lines
is undefined. This is useful for preallocating lines which are to
be completely overwritten, for example in a block copy
operation.
HAL_DCACHE_FLUSH()
Invalidates all cache lines in the region after writing any
dirty lines to memory.
HAL_XCACHE_INVALIDATE()
Invalidates all cache lines in the region. Any dirty lines
are invalidated without being written to memory.
HAL_DCACHE_STORE()
Writes all dirty lines in the region to memory, but does not
invalidate any lines.
HAL_DCACHE_READ_HINT()
Hints to the cache that the region is going to be read from
in the near future. This may cause the region to be speculatively
read into the cache.
HAL_DCACHE_WRITE_HINT()
Hints to the cache that the region is going to be written
to in the near future. This may have the identical behavior to
HAL_DCACHE_READ_HINT().
HAL_DCACHE_ZERO()
Allocates and zeroes lines in the cache for the given
region without reading memory. This is useful if a large area of
memory is to be cleared.