LCStoreBlocks

C Specification

#include <revolution/os/OSLC.h>
void LCStoreBlocks(void* destAddr, void* srcTag, u32 numBlocks);

Arguments

destAddr Start address of the transfer destination in memory. Must be 32 byte-aligned.
srcTag Start address for the locked cache address to copy to destAddr. Must be 32 byte-aligned.
numBlocks Transfer size (number of cache blocks). Must be a value from 0 to 127. If zero is specified, the transfer size is 128 blocks (4 KB).

Return Values

None.

Description

Enqueues a single DMA transfer for moving data in a locked cache to main memory. This function is more efficient than calling the LCStoreData function, but has a maximum transfer limit 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 implies a transfer size of 128 blocks. The range of valid transfer source addresses is the 16KB region starting from the value returned by the LCGetBase function.

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

The only ways to determine if the transfers are complete are to poll the length of the DMA queue with the LCQueueLength function or to wait until the queue length reaches a certain value with the LCQueueWait function. See the following example. 

A maximum of 15 outstanding DMA transfers in the DMA queue is allowed. If the queue overflows, a machine check exception occurs.

The locked cache must be enabled throughout the transfer, otherwise a machine check exception will occur during the DMA.

If the DMA finds source data in the 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 load and store at any given time. When a buffer has finished storing its old (just processed) data, this information can be used to ensure that loading the next block of data to process has been completed.

// 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