We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
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
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 :(
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.
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.
"So I have to give up the SMALL mode and use the LARGE mode."
Can you not, as I just suggested, edit the type definitions to include the 'xdata' keyword?
For example:
#if defined _MSC_VER // These definitions when using MSVC typedef unsigned char U8; /* Unsigned, 8 bits */ typedef signed char S8; /* Signed, 8 bits */ #elif defined __C51__ // These definitions when using Keil C51 #define U8 xdata unsigned char U8 /* Unsigned, 8 bits in XDATA */ #define S8 xdata signed char U8 /* Signed, 8 bits in XDATA */ #else #error Unknown compiler #endif
then you could continue to use the SMALL model...
I take Andy's suggestion one step further, and actually have different files for different compilers. Rather than run down a series of #ifs, the build system (make, jam, uVision, whatever) just includes only the header appropriate to the tools in use. No #if maintenance required.
Presumably the OP is in control of his build system, and can perhaps substitute the "local conventions typedefs" file for the one used by the owners of the code that can't be changed.
"I take Andy's suggestion one step further, and actually have different files for different compilers."
Ah yes - you've mentioned it before. It sounds a jolly good idea - I might change to doing it that way...
I would still include a check in each file to prevent it being "accidentally" used with the wrong compiler; eg,
// c51.h #ifdef __C51__ // C51 stuff here #else #error Wrong compiler! #endif // end of file