Hello, Some of the variables that my program uses(may contain also big ,multidimensional arrays) have default values, which are used during the code operations and may be modified during the program's runtime. defining a variables using:
volatile xdata arrayName = [0x01, 0x03, 0x02, 0x04...];
volatile code arrayName = [0x01, 0x03, 0x02, 0x04...];
No, there is no such method. Because there can't be. Initializers have to be in read-only code memory so you can load them into the device as part of the program, where they will survive a power-cycle of the device. But modifiable variables must be in RAM. Thus, an initialized modifiable variable must exist in two separate copies. Nothing to be done about it. There's one possible way around this, though: computed startup values. I.e. you can do the initialization manually, instead of leaving it to the compiler, and express it in a more compact manner than a list of values. If you're lucky.
"Initializers have to be in read-only code memory ... where they will survive a power-cycle of the device." They don't absolutely have to be in CODE space. If you have non-volatile memory in XDATA space, then it can be done. Search for XCONST for details. You may need special tools to be able to write the initial values into the non-volatile XDATA area... Even with non-volatile XDATA, if you want the initial values restored on reset, you will still need to save the reset values somewhere, and have some code to copy them to the working area.
Dear Hans, In the application that I am working on - both the code and the xdata areas will be located in a 64KByte of RAM. During the reset stage, the program code will be loaded into the 8051's RAM by an external controller, and only after the 8051's code is loaded into it's RAM - the 8051 will be unreset. Therefore, there is no point in creating a code that will hold the default values of the variables (which, BTW, is not computable) in a place in the RAM that holds the code, and then copy the same init values into the xdata area in the same RAM (and by doing that, duplicating the initiated variables size). Defining a variable to be in the code space will put the default values in a single place in the HEX file (that will be loaded into the RAM), but' as I said before, will case a restriction: The array will be read only. About Andrew's answer: XCONST is not mentioned in the C51 User guide. I didn't see any place that describes and tells me if this can declare a modifiable variable, but by the name I can guess that it is also not writable are. Am I correct ? Is there any other way that you can think of, that will help me get the functionality that I need ? Amit.
http://www.keil.com/support/man/docs/c51/c51_userclass.asp Also do a 'Search' of the Forum & Knowledgebase
http://www.keil.com/support/man/docs/c51/c51_userclass.asp Also, do the 'Search' of this forum, and the Knowledgebase.
Hmmm... dunno why that came up twice...?
I saw that link already. ( http://www.keil.com/support/man/docs/c51/c51_userclass.asp ) It says "XCONST - Constants in const xdata space (XDATA class)." but doesn't say whether it is a modifiable area (variable) or not. Also, doesn't the fact that it is not mentioned in the C51 User guide means that it may not be supported by the C51 compiler / linker ? Amit.
XCONST wouldn't help him --- he wants these objects to be runtime-modifiable. The ultimate catch here is that what he's trying to do can't be expressed in C. A C variable is either initialized (at compile/link time, putting the initializer in CODE and the variable in XDATA), or it's not (then there's no way to specify an initializer at all). This means the initializers would have to be generated by some other means. A separately compiled & linked assembly project filling a XCONST segment at the relevant address could work. Meaning that boot-loader would have to load two hex-files into different address spaces (unless those 64K are von-Neumann).
"... it is not mentioned in the C51 User guide means ..." Which particular version(s) of the guide(s)? I think the latest is the online version; the printed versions (including the PDFs installed with the tools) are quite out of date? It certainly works with the current C51, but does require LX51 (not BL51).
"doesn't say whether it is a modifiable area" True. I'm not sure about that. You may need to contact Keil support direct on that one.
"program code will be loaded into the 8051's RAM by an external controller" In that case, you could remove the initialisation from the 8051 code, and supply it separately to your loader. You would either need to fix the table locations (eg, using _at_, or Linker controls), or devise some means to extract this information from the Keil outputs (eg, from the Linker Map file)
Andrew, First of all thanks for your answer, time, and good will. About what you wrote: "…In that case, you could remove the initialization from the 8051 code, and supply it separately to your loader": I thought of this bypass-solution and came to conclusions that I will do that as a last option, if I will have no other way to do it as I wanted to do. There are 2 problems when working as you have suggested: 1) Complexity and vulnerability issues: A separate application will have to mange the default values of some of the code. This is a window for bugs and mismatches, since the SW is becoming dependet on external tool and stops from functioning as a stand-alone code. There is also new dependency between the memory locations declared in the code using the "_at_" declaration and the location where the tool will put the values, which brings more complexity to the application. Another issue is the SW version's control. Now a build of the SW will be independet from the default values of the arrays and the variables. 2) Keil's HW Debugger's issue: The Keil HW Debugger uses the linker's generated OMF file. This file will be loaded into the RAM, and this means that the Keil's debugger will not load the external default values when using it as a debugger. About the XCONST: I use the BL51 linker, not the LX, so it probably is not relevant anyway, and no matter what the answer is about if this declares any constant or variable memory type. Keil's support: Do you have any solution to the problem mentioned in this thread ? Thanks, Amit.
It will generate code are that will hold the array's default values, The size needed, where else would you get them from? as well as code that in the beginning of the program startup will copy theses values into the arrays themselves. That is so little code, that, if that hurt you, you are in deep doo-doo anyhow. I think you are trying to make the "'51 PC" (your question and "multi-dimenisional arrays" indicate that this is the case) as so many other mistaken individuals, if that is what you are trying to do, then do not expect '51 tools to help you. The '51 is not (and has never been intended to be) a "load before run" device".. It is a "program in permanent storage device", so that is what the tools are made to support, thus they work the way they do. As it has been suggested, if you do not like that the tools work in '51 mode, do not use the tools, make your own. Erik
In the application that I am working on - both the code and the xdata areas will be located in a 64KByte of RAM. During the reset stage, the program code will be loaded into the 8051's RAM by an external controller, and only after the 8051's code is loaded into it's RAM - the 8051 will be unreset. Well, that sure makes things easier. Declare your array in code space. For example:
char code arrayNameRO = [0x01, 0x03, 0x02, 0x04...];
volatile char xdata *arrayNameRW = arrayNameRO;
John, Even though that the functionality that I was looking for is not available in the compiler/linker - your idea will solve my problem in a simple way. Thank you ! .......Amit.