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 ?
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
"...and the possibility of error increases with each step." Of course my ever-unpopular response (you've heard it all before) is to incorporate software tools (sed, awk, perl, etc.) to automate your build process.
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. Are you saying that the third party utility generates a HEX file? That's what "Production need to be able to combine the calibration coefficients (generated by some 3rd party utility) with the hex file output" sounds like to me. If that's right, then one can assume that the calibration data is stored in ROM (CODE space). And, merging the calibration data with the HEX file really means replacing the calibration data from the C program with the calibration data from the 3rd party utility. So, if that's the case, why can't you just have a HEX file with default calibration data that gets merged in by default? 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. I don't know that that's the ONLY reasonable way to do it. Off the top of my head I could see using an assembly file to do that. With more details about what the ultimate goal is, I can probably dream up more ways than that. I've got numerous products in the field that have default and calibrated configuration data and I didn't have to jump through hoops to get it to work. ...the linker will allow you to link the resulting object code outwith the code space defined in the project options without giving a warning. I'm not sure what you mean here. 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? As I've said before, this modification would require changes to the object code generated (new record types would have to be added because this is not supported in the Intel OMF51 specification). Adding new record types would require that we contact every emulator and other third party vendor that uses the OMF51 object module specification. That's about 100 vendors or so. When we have made changes in the past, it typically took 3-5 years for other vendors to catch-up and implement support for these new record types. Needeless to say, when we add that feature (yes, it is on the list of features to add) we will likely be plagued by developers who can't use it with their existing tools. That means they'll need to upgrade all of those tools. And, that just makes Keil look like the bad guy. Jon
All this sounds like a discussion on comp.lang.c.moderated this Saturday when a poster asks: "how does one align a static struct to a 4kb boundry? [sic]" We get two radically different answers from two renowned C experts: Dan Pop replies "In standard C, one doesn't." Jack Klein says "One doesn't, in standard C." I had to utter a little chuckle. Of course, help was provided on how to do it with the proper elements in a typical toolchain (e.g., assembler, linker, and yes the compiler too -- but with #pragma). In fact, I've got a PowerPC compiler here that has a pragma for specifying special alignment. Now back to the request of extending the _at_ extension specifically, Jon says "yes, it is on the list of features to add". Well, kudos to Keil for listening to their customers, but I also have to give kudos to all those customers who solve these kinds of problems day in and day out without the need for language extensions or extended language extensions. At least we won't have this to talk about any longer. Jon, I have to wonder if this OMF extension could be switched on at the command lines of the compiler and linker, so that for the vast majority of users not requiring the _at_-initializer feature, it would be "transparent".
Extensions such as the _at_ keyword are very useful and appropriate in this environment. Just because a feature is useful doesn't mean it's a good idea to add it. All the more so if the feature isn't strictly necessary to achieve the goal. The same functionality you get with the rather limited _at_ feature can be had completely without it. You would put the relevant objects into named sections of their own, and then tell the linker that those sections are to be placed at certain absolute addresses. Done. With that in mind, _at_ is really just syntactic sugar, and, as Jon pointed out in his reply, it's actually not all that sweet sugar, either. Another thing to keep in mind is that if you insist on a fixed address for your configuration data, that means you put an unmovable obstacle somewhere inside the code memory range. This will result usually in a hole in code space usage, i.e. waste of precious resources --- something I would have guessed would bother you considerably.
Jon, I have to wonder if this OMF extension could be switched on at the command lines of the compiler and linker, so that for the vast majority of users not requiring the _at_-initializer feature, it would be "transparent". Yes, but do we really need to add another command-line directive and checkbox in uVision? Jon
"Yes, but do we really need to add another command-line directive and checkbox in uVision?" The alternative being what -- always generating the new OMF51+ format only? Or is it that the command-line (and checkbox) is an idiotic way to support old and new OMF51 formats? Sorry, I was merely making a suggestion for how to keep developers and tool vendors happy during the 3-5 year catch-up period and not "look like the bad guy". I did not necessarily intend to say "you must use a command line switch", but rather to suggest keeping support for the standard OMF51 format by default so nobody's tools break until they absolutely must have this _at_-initializer thing. By the way, if you need an example of what an embedded customer/developer is willing to tolerate as far as the number of command-line options, take a look at gcc! :-) http://gcc.gnu.org/onlinedocs/gcc-3.3.1/gcc/Option-Summary.html#Option%20Summary
Dan, I didn't mean to offend you with that post. The alternative being what -- always generating the new OMF51+ format only? New records would only be generated if the _at_ = {x, y, z }; is used. So, if you don't use that, there would be no problems. If you have an emulator that doesn't support the absolute assignment record...don't use that...#ifdef it out. GCC sure does have a lot of options. I had to get a GCC port up and running the other day and it took me a while to figure out if I was generating the best code or the worst. Our compiler option list is starting to look like the GCC option list. The problem is that many users start by setting all kinds of options (without understanding all the ramifications) and that just gets them into trouble. And, that's what I want to avoid. Jon
"New records would only be generated if the _at_ = {x, y, z }; is used. So, if you don't use that, there would be no problems." Ah, I see -- excellent, and no need for options. "If you have an emulator that doesn't support the absolute assignment record...don't use that...#ifdef it out." Plus, if in emulator does not support that new record type, it's quite likely that a little emulator command script could initialize those memory locations as if they had been initialized during code load. "GCC sure does have a lot of options. I had to get a GCC port up and running the other day and it took me a while to figure out if I was generating the best code or the worst." What? You mean it wasn't intuitively obvious? ;-) "Our compiler option list is starting to look like the GCC option list. The problem is that many users start by setting all kinds of options (without understanding all the ramifications) and that just gets them into trouble. And, that's what I want to avoid." Absolutely! The presence of new records only if the _at_-initializer is used certainly avoids that. Thanks for sharing your notion of how the OMF51 compatibility issue would be addressed. /Dan Henry