LCStoreBlocks

Syntax

#include <revolution/os/OSLC.h>

void LCStoreBlocks(void* destAddr, void* srcTag, u32 numBlocks);

Arguments

destAddr Start address of the destination in memory. Must be 32-byte aligned.
srcTag Start address for the locked cache address to be copied to destAddr. Must be 32-byte aligned.
numBlocks Transfer size. (Number of cache blocks.) Must be specified as a value between 0 to 127. If 0 is specified, the transaction size used is 128 blocks (4KB).

Return Values

None.

Description

Enqueues a single DMA transfer for moving data in a locked cache to main memory. Using this function is more efficient than calling the LCStoreData function, but it is limited to a maximum transaction of 128 cache blocks (4 KB) and performs no error checking. Addresses are assumed to be 32-byte aligned, and numBlocks is assumed to be a value from 0 to 127. Note that a value of zero for numBlocks indicates a transaction size of 128 blocks.The range of valid source addresses is the 16KB region starting from the value returned by LCGetBase.

See the following example code that performs quadruple buffering within a locked cache region with this function. This sample code example is the same as the sample code for the LCStoreData function.

The only methods to determine whether a transaction has completed are either to poll the length of the DMA queue with the LCQueueLength function or to wait until the queue length reaches a fixed value with the LCQueueWait function. See the following example.

Note that a maximum of 15 DMA transactions can be issued in the DMA queue. If the queue overflows, a machine check exception occurs.

The locked cache must be enabled throughout the transfer; or else a machine exception will occur during the DMA.

If the DMA finds a source address in normal cache, a machine check exception occurs.

Example

The following code example splits the locked cache into 4 buffers, and ping-pongs between them to process a large array in main memory. The code is structured so that each buffer at most has one outstanding unsent load and store at any given time. This fact is used to ensure that a buffer completed storing its old (just now processed) data and then completed loading the block of data to process next.

// define 4 4k buffers in locked cache region
// note that NUMBUFFERS * BUFFER_SIZE <= 16k
#define BUFFER_SIZE (4*1024)
#define NUM_BUFFERS (4)

#define DATA_ELEMENTS (10*1024*1024)
:
// real mem loc of Buffers[i] is at BufAddr[i]
u8* Buffers[NUM_BUFFERS];
u8* BufAddr[NUM_BUFFERS]; 
:

void main ()
{
    u8* data;
    u8* currDataPtr; // offset into data
    u32 i;
    void* arenaLo;
    void* arenaHi;

    OSInit();
    LCEnable();

    arenaLo = OSGetArenaLo();
    arenaHi = OSGetArenaHi();
    :

    OSReport("Splitting locked cache into %d buffers\n", NUM_BUFFERS);

    for (i = 0; i < NUM_BUFFERS; i++)
    {
        Buffers[i] = (u8*) ((u32)LCGetBase() + BUFFER_SIZE*i);
        OSReport("Locked Cache : Allocated %d bytes at 0x%x\n", 
                    BUFFER_SIZE, 
                    Buffers[i]);
    }

    // Initialize source data
    data = (u8*)OSAlloc(DATA_ELEMENTS * sizeof(u8));
    :
    DCFlushRange(data, DATA_ELEMENTS);
    
    OSReport(" Test 2 : using low level interface for DMA load/store\n");

    for (i = 0; i < NUM_BUFFERS; i++)
    {
        BufAddr[i] = data + BUFFER_SIZE*i;
        LCLoadBlocks(Buffers[i], BufAddr[i], 0);
    }

    currDataPtr = data + BUFFER_SIZE * NUM_BUFFERS;

    LCQueueWait((NUM_BUFFERS-1));

    while (currDataPtr <= data+DATA_ELEMENTS)
    { 
        for (i = 0; i < NUM_BUFFERS; i++)
        {
            LCQueueWait((NUM_BUFFERS-1)*2);
            ProcessBuf(Buffers[i]);
            LCStoreBlocks(BufAddr[i], Buffers[i], 0);
            LCLoadBlocks(Buffers[i], currDataPtr, 0);
            BufAddr[i] = currDataPtr; // move to next unprocessed buffer

            // advance the next block to be read
            currDataPtr += BUFFER_SIZE;
        }
    }
    LCQueueWait(NUM_BUFFERS); // don't care about last dma's
    :
    OSHalt("Test complete");
}

See Also

Cache Functions, LCEnable, LCStoreData, LCLoadBlocks, LCQueueLength, LCQueueWait

Revision History

2006/03/01 Initial version.


CONFIDENTIAL