Back to ESAcademy Home Page


www.philipsmcu.com8051 Memory Configuartions with C Compilers

by Andy Ayre, ESAcademy
based on the C51Primer, by Mike Beach, Hitex UK

The Keil and Raisonance C Compilers provide a variety of memory models. When do we choose which model?

[ Introduction | Available memory models | Choosing a model | Using a model ]

 

Home

News

Training Classes

Products

Consulting

Technical Library

Contact Us

Recommended Books

Setting The Memory Model - #Pragma Usage

The overall memory type is selected by including the line

#pragma <MemoryModel> (for example "SMALL")

as the first line in the C source file.

SMALL is the default model and can be used for quite large programs, provided that full use is made of PDATA and XDATA memory spaces for less time-critical data.

Special note on COMPACT model usage

The COMPACT model makes certain assumptions about the state of Port 2. The XDATA space is addressed by the DPTR instructions that place the 16-bit address on Ports 0 and 2. The COMPACT model uses R0 as an 8-bit pointer that places an address on port 0. Port 2 is under user control and is effectively a memory page control. The compiler has no information about Port 2 and unless the user has explicitly set it to a value it will be undefined, although generally it will be at 0xff. The linker has the job of combining XDATA and PDATA variables and unless told otherwise it puts the PDATA (COMPACT default space) at zero. Hence, the resulting COMPACT program will not work.

When using the Keil Compiler it is essential to set the PPAGE number in the startup.a51 file to some definite value - zero is a good choice. The PPAGEENABLE must be set to 1 to enable paged mode. Failure to do this properly can result in very dangerous results, as data placement is at the whim of PORT2!

The Raisonance Compiler sets up P2 and enables paged mode automatically.
When linking, the PDATA(ADDR) control must be used to tell the linker/locator where the PDATA area is.

Local Memory Model Specification

Overview

The C compiler allows memory models to be assigned to individual functions. Within a single module, functions can be declared as SMALL, COMPACT or LARGE:

    #pragma COMPACT 

    /* A SMALL Model Function */ 
    fsmall() small { 
    printf("HELLO") ;
    } 

    /* A LARGE Model Function */ 
    flarge() large { 
    printf("HELLO") ;
    } 

    /* Caller */ 
    main() { 
    fsmall() ; // Call small func.
    flarge() ; // Call large func. 
    } 
    

A Point To Watch In Multi-Model Programs

A typical 8051 C program might be arranged with all background loop functions compiled as COMPACT and all (fast) interrupt functions treated as SMALL. The obvious approach of using the #pragma MODEL to set the model can cause odd side effects. The problem usually manifests itself at link time as a MULTIPLE PUBLIC DEFINITION error related to, for instance, putchar().

The cause is that in modules compiled as COMPACT, the compiler creates references to library functions in the COMPACT library and the SMALL modules will access the SMALL library. When linking, two putchars() from two different libraries are found.

The solution is to stick to one global memory model and then use the SMALL function attribute, covered in the previous section, to set the memory model locally.
Example:

    #pragma COMPACT
    void fast_func(void) SMALL{
    /*code*/ 

[ Introduction | Available memory models | Choosing a model | Using a model ]