
282
Evaluating and Programming the 29K RISC Family
with data held in cache. Accesses to other address regions or on–chip peripherals are
not cached. When polling the status of a peripheral device, it is important that status
data not be cached. This means that off–chip peripherals should be placed in PIA
space or other non cached space.
When developing code in the C programming language, the key word
volatile
can be used to indicate that data should not be held in internal registers. However, this
data may still be cached. Hence, marking data volatile is insufficient to ensure that it
is always accessed from off–chip memory. If memory can be modified by some other
device, either via dual–port memory or external DMA controller, it is important that
the cache be kept coherent with memory. This can be accomplished by signaling the
processor when a DMA type transfer is complete. The processor can then invalidate
the cache. Because the cache normally contains a copy of the memory data (due to the
write–through policy), all modifications to cached data are already reflected in the
memory state. Note that marking data
volatile
may reduce the compilers ability to
produce highly optimized code, as load scheduling is restricted across the boundary
created by a volatile memory access.
Cache invalidation due to DMA type access can be avoided if the data
concerned is never cached. There is no way with the Am29240 microcontroller of
marking the data as non–cacheable. However, data which is accessed via LOADL
(load and lock) instructions is never allocated for cache use. A convenient way of
ensuring that the compiler only generates code which accesses the critical data with
LOADL and STOREL instructions has been added to newer versions of the High C
compiler. When the key word
_LOCK
is used (along with
volatile
) to define the data
type of a variable, LOADL instructions are used in place of LOAD when accessing
the associated data. Consider the example below:
typedef _LOCK volatile unsigned char UINT_8;
unsigned char uart_data;
UINT_8 *uart_p;
/* cacheable copy of UART data */
/* uart_p must hold uart address */
uart_data = *uart_p;
/* access the UART */
If the
_LOCK volatile
approach is not available, it may be possible to take an
object–orientated approach to DMA affected data. The critical data could be only
modified with an object member function. The member function (probably a leaf)
could be written in assembler and use the LOADL instruction. Of course using such a
simple function to perform a task which would normally be accomplished with
in–line code, would have a performance impact. However, this may be better than
invalidating the whole cache with each DMA occurrence. Note that directly setting
the Lock (LK) bit in the Current Processor Status (CPS) register will ensure that the
Lock pin is asserted during load and store operations, but does not result in data cache
bypassing.