10.3 Using Overlays

The total application code size and data will probably be greater than what is actively being used at any point in time. To conserve DRAM, applications may choose to only have active code and data resident. To facilitate this, the application can be partitioned into a number of segments, where some segments share the same memory region during different phases of execution. Here is an excerpt from a specification file that contains a kernel code segment that can call routines in either of two overlay segments, texture and plain:

beginseg
    name    "kernel"
    flags   BOOT OBJECT
    entry   boot
    stack   bootStack + STACKSIZE
    include "kernel.o"
    include "$(ROOT)/usr/lib/PR/rspboot.o"
    include "$(ROOT)/usr/lib/PR/gspFast3D.o"
endseg

beginseg
    name    "plain"
    flags   "OBJECT"
    after   "kernel"
    include "plain.o"
endseg

beginseg
    name    "texture"
    flags   "OBJECT"
    after   "kernel"
    include "texture.o"
endseg

beginwave
    name    "overlay"
    include "kernel"
    include "plain"
    include "texture"
endwave

Note the use of the after keyword to place both of the overlay segments at the same address. Also note that makerom must be called with the -o option to disable the checking of overlapping segments in the above specification file.

Prior to loading a segment into memory, the application must invalidate the corresponding instruction and data cache lines. The makerom() makes appropriate symbols available to the application that can be used to construct the arguments to the osInvalICache() and osInvalDCache() routines. Then the actual DMA from ROM to DRAM may be performed, as well as the clearing of the uninitialized data (BSS) section of the segment. Again, makerom() generated symbols may be used for the bzero() call. After the segment is loaded, any procedure in the segment may be called or any data in the segment referenced. Following is sample code that illustrates the entire process:

extern    char    _plainSegmentRomStart[],_plainSegmentRomEnd[];
extern    char    _plainSegmentStart[];
extern    char    _plainSegmentTextStart[],_plainSegmentTextEnd[];
extern    char    _plainSegmentDataStart[],_plainSegmentDataEnd[];
extern    char    _plainSegmentBssStart[],_plainSegmentBssEnd[];

osInvalICache(_plainSegmentTextStart,
    _plainSegmentTextEnd-_plainSegmentTextStart);
osInvalDCache(_plainSegmentDataStart,
    _plainSegmentDataEnd-_plainSegmentDataStart);
osPiStartDma(&dmaIOMessageBuf,OS_MESG_PRI_NORMAL,OS_READ,
    (u32)_plainSegmentRomStart,_plainSegmentStart,
    (u32)_plainSegmentRomEnd - (u32)_plainSegmentRomStart,
    &dmaMessageQ);

bzero(_plainSegmentBssStart,
    _plainSegmentBssEnd-_plainSegmentBssStart);
(void)osRecvMesg(&dmaMessageQ, NULL, OS_MESG_BLOCK);

UP