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.
How can one locate a table of constants at a certain address in C ?
Or use the Linker
Although, as you'll probably want to initialise your constants you'll find the _at_ keyword useless. Hands up everybody who'd like to be able to use initialisers with the _at_ keyword! Stefan
So that leaves the Linker, then. BTW: Why do these constants need to be at a particular address?
Well, let us suppose we have a measurement system and these constants represent calibration coefficients. Any time the sensors are calibrated, we have to redefine the table of coefficients. To redefine the coefficients, we must know where they are are located in program memory ( I mean flash memory, of course).
I am new to C, and perhaps this is why I don't quite understand you. Please tell me what is the trouble with the 'at' keyword.
There is no trouble if it is external flash accessed as external DATA. In this case just use:
unsigned char xdata table1[size_1] _at_ address_1; unsigned char xdata table2[size_2] _at_ address_2;
But if it is PROGRAM memory (CODE segment) then you should use linker options because it is not possible to do something like:
unsigned char code table_1[size_1] _at_ address_1 = "blabla";
Well, Andrew Neil asked a good question - why do you need with fixed address? For simple example, you have 4 tables of coefficients, each one contains 8 bytes. So then do something like (put your values here):
unsigned char code tables[4][8] = { {1,2,3,4,5,6,7,8}, {11,12,13,14,15,16,17,18}, {31,32,33,34,35,36,37,38}, {71,72,73,74,75,76,77,78}, };
unsigned char *current_table; switch (redefine_condition) { case condition_1: current_table=tables[0]; break; case condition_2: current_table=tables[1]; break; case condition_3: current_table=tables[2]; break; case condition_4: current_table=tables[3]; break; }
"To redefine the coefficients, we must know where they are are located in program memory" But why does it need to be fixed? The compiler can find the address of any object at run-time by using the '&' address-of operator!
"Please tell me what is the trouble with the 'at' keyword" Note that the keyword is '_at_' - complete with the underscores! Did you read the description in the Manual, in particular the two restrictions stated at the foor of the page? That answers your question
To redefine the coefficients, we must know where they are are located in program memory Do you mean without modifying the source file and building the project and re-flashing the entire program to memory? Jon
>But why does it need to be fixed? I want to rewrite the table of coefficients with the help of bootloading software. I set my chip in 'BIOS' mode, perform the necessary operations and then reactivate my program. In 'BIOS' mode my chip doesn't 'know' where the coefficients are located. In this mode it can only perform generic read/write operations. So I must provide the fixed address.
Okay, if you always know about values of fixed addresses then you may use direct addressing in your program. For example, coefficients' tables are always placed at addresses 0x1234, 0x2345, 0x3456 and 0x4567. Then for redefinition, just use: current_table = 0x2345 etc. Good days!
"Do you mean without modifying the source file and building the project and re-flashing the entire program to memory?" Jon, Imagine this scenario: The product reads data from various sensors which have to be individually calibrated in isolation from the product. Production need to be able to combine the calibration coefficients (generated by some 3rd party utility) with the hex file output by Keil before programming the 8051 code space. For ease of development you want to have a default set of coefficients present in the source code. The only reasonable way to achieve the above is to separate all these coefficients out into a single source file, select "Keep variables in order" and link this at the appropriate address. Oh, and watch out that you don't have any uninitialised constants in that file as "Keep variables in order" is ignored for them. Before you ask why I use uninitialised constants: they act as padding in some situations. I wouldn't need them if I could locate and initialise with the _at_ keyword. Another problem with the above approach is that the linker will allow you to link the resulting object code outwith the code space defined in the project options without giving a warning. How nice it would be to be able to use the _at_ keyword to declare and initialise code space constants at a place in the source code which is appropriate to the structure of the program? This question comes up again and again and again - when are you guys going to implement this? Stefan
The problem arises from your try to use the compiler to do things that are not a compiler's job. Arguably, the error is that the _at_ keyword even exists, not the way it's implemented. The project you outline can be handled with next to no hassle, without hardwiring any addresses or the _at_ keyword. Here's how: 1) Compile the project straightforwardly, let the linker decide wherever it wants to place those constants. 2) Look into the map file to find the addresses the linker placed the relevant objects. 3) Let the 3rd-party tool generate a raw binary file for the replacement data. 4) Using the address from step 2) and the file from step 3), create a correctly addressed hex file 5) merge that with your application .hex file 6) burn.
"The problem arises from your try to use the compiler to do things that are not a compiler's job. Arguably, the error is that the _at_ keyword even exists, not the way it's implemented." Well, I disagree with this. The Keil compiler is intended to address a specific problem - programming embedded systems. Extensions such as the _at_ keyword are very useful and appropriate in this environment. Unfortunately your solution is too restrictive - every time the code is modified the linker will probably place the constants at a different address. I would have to modify the utility that merges the constants with the code to read the .map file for each build, I would have to issue the .map file along with each build etc etc, and the possibility of error increases with each step. Stefan