This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Allocate the global variables to XDATA in small memory model

I have a MCS51 project which is compiled in small memory model, now I want to add a module to the project, the source files of the module comes from other non-C51 project, so I want to compile these source files with C51 in small memory model, but want to allocate all the global variables in this module to the XDATA ram.
I don't want to modify each variable to XDATA one by one, so is there any simple way to implement this requirment?

Your kind support is highly appreciated!

Thanks & Regards
aolin

Parents
  • Hi,
    I tried #pragma LARGE just before the variables, and then #pragma SMALL before the code start, like:
    <1>
    <2>#pragma LARGE
    <3>unsigned char message[8];
    <4>unsigned char checksum;
    <5>
    <6>#pragma SMALL
    <7>void message_process(void)
    <8>{
    <9> unsigned char i;
    <10>
    <11> checksum = 0;
    <12> for( i=0; i<8; i++)
    <13> checksum += message[i];
    <14>}

    but it doesn't work!
    The compiler complained:
    FUNC.C(6): error C252: misplaced primary control, line ignored

    How to set LARGE for variables only, and then set back to SMALL for code?

    Thanks!

Reply
  • Hi,
    I tried #pragma LARGE just before the variables, and then #pragma SMALL before the code start, like:
    <1>
    <2>#pragma LARGE
    <3>unsigned char message[8];
    <4>unsigned char checksum;
    <5>
    <6>#pragma SMALL
    <7>void message_process(void)
    <8>{
    <9> unsigned char i;
    <10>
    <11> checksum = 0;
    <12> for( i=0; i<8; i++)
    <13> checksum += message[i];
    <14>}

    but it doesn't work!
    The compiler complained:
    FUNC.C(6): error C252: misplaced primary control, line ignored

    How to set LARGE for variables only, and then set back to SMALL for code?

    Thanks!

Children
  • Looks like bad advice from me. The manual entry from the error message says:

    Description Primary controls must be specified at the start of the C module before any #include directives or declarations.

    And early on, in Compiling Programs / Directives, the manual says

    Some directives may be specified only once at the beginning of a source file. If one of these directives is specified more than once, the compiler generates a fatal error and aborts compilation.

    So, it looks like the memory model is one of these primary directives that can only be specified once per file.

    If you need to split the functions from the data, I suppose you'll have to break it into two files.

  • It seems I have to modify the variables one by one, no choice!

    Thank you very much!

  • Yes, I think you're right!

    There are different versions of the runtime support libraries for each memory model - so I think the tools may get confused if you mix different models in the same project!

    As it's only the globals, and for only one "module" of your project, it shouldn't be too hard to apply the 'xdata' keyword...?

  • this may seem more cumbersome, but I think it will be easier and safer in the end.

    just a suggestion, but that is how I would do it to avoid the pesky little 'forgets'

    In the below you can use your own names whatever you prefer. I show just unsigned char, you will, of course have to make all.

    a .h module you include in all sources
    #define UX8 unigned chat xdata
    #define UD8 ondigned char

    then do a global replace of unsigned char with U_8
    then in every module replace U_8 with UX* or UD8

    by this anything you 'forget' will come up as an error

    Erik

  • WTF is unigned chat
    WTF is ondigned

    ???

  • thumbs used for typing

    WTF is unigned char
    WTF is unsigned

    I am sorry, sometimes in the preview I see what I ment, not what I typed, my bad :(

    Erik

  • I created #define's for memory areas that I use in declarations, along with all my other conventions:

    Platform-specific defines.h
    --
    #define BULK xdata
    #define FAST data

    Other Files:
    --
    U8 BULK example;

    With this scheme, it would be easy to override the implementation of "BULK" for one particular file.

    (To really insulate yourself from vendor-specific syntax, these macros really need to be functions that rewrite the entire declaration. There's no guarantee that a simple keyword in a given position will suffice. So this is really only a half-hearted solution to isolating the language extensions. But it's easy, and still has some benefits.)

  • Yes, if all the code is done by me, I will do it like this way. But unfortunately the add-on module comes from other non-C51 project, which is in standard C syntax and maintained by other guys.
    That module has a bundle of source files, I have to modify one by one, that is a tough thing!

  • "the add-on module comes from other non-C51 project"

    In that case, it is not likely to be optimised for the 8051 anyhow - so can you just change the whole project to the LARGE model?

    "That module has a bundle of source files, I have to modify one by one, that is a tough thing!"

    The tradeoff is always the same: do you want to save developer time at the cost of runtime size/performace, or do you want to spend development effort to minimise runtime requirements?

  • "the add-on module comes from other non-C51 project, which is in standard C syntax and maintained by other guys."

    How likely is it that "they" will make changes to "their" code, and you will have to incorporate them?

    Ideally, you should agree some scheme such as Drew suggested with the "owners" of this code - so that you won't have to repeat the exercise...

    Failing that, if you are likely to have to repeat it, you should look into creating some sort of script or macro to automate it...

  • But unfortunately the add-on module comes from other non-C51 project, which is in standard C syntax and maintained by other guys.
    instead of inserting XDATA in "the other guys code" select the LARGE model and insert DATA in your own code.

    Erik

  • You can apply the compiler directives on the command line. So, if you could at least get the owners of the code to separate the variable declarations from the functions, you could set just the variables to the large model.

    If you have to keep the code with the variables, then all your code will need to be large model. In that case, the simplest thing seems to be to do as others have suggested: change all the rest of the code that you do own to explicitly declare the variables as "data", so you can build with the large model.

    Incidentally, the conventional wisdom is that all variables should have explicit memory qualifiers just to problems when changing memory models. (Default actions by the compiler keep showing up in languages, and they always seem to turn out to be more annoying than convenient. Implicit integer declarations based on the first character of the identifier in FORTRAN, implicit function return values in K&R C, implicit type conversion from single-argument constructors in C++... just say "no" to implicit behavior.)

  • If you're using code that wasn't written for the 8051, then there's a high probability that it won't work unless the authors have been careful to avoid the "standard" C types - char, int, etc.

    Hopefully, they have at least used "portable" typedefs like

    typedef unsigned char U8; // Unsigned, 8 bits
    typedef   signed char S8; // Signed,   8 bits
    


    In that case, all you need to do is to modify these to include the XDATA specifier (not sure if that can be done in a typedef, or if you'll need a #define)

    If they haven't done this, then getting the variables into XDATA may well be the least of your problems...

  • Thanks for everybody's effort here!
    I tried the SMALL memory model to compile the add-on module, but fail in linking stage, the DATAGROUP for auto, local variables is too large to fit in the 8052 internal memory!
    So I have to give up the SMALL mode and use the LARGE mode. The cost is the code size is arround 8KB bigger than the SMALL mode!

  • You can still use the small memory model, just as long as you have a couple of larger memory variables that you can specifically force out by specifying XDATA.

    The difference between the memory models is not what memory areas that can be used, but what memory areas that are used by default.