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.
Hi everyone, j developed a C program that use the philips 87LPC764 8051 derivative. This micro needs to store at specific addresses in code memory 2 bytes for the configuration options (type of oscillator, speed etc.)...how can j do this? Maybe using the "_at_" keyword? Any ideas welcomed bye! Massimo.
I ask why? Why do you need a variable at a particular address? I've used the _at_ directive to memory map hardware and it works great. I certainly wouldn't want initial values written to my hardware outside my control. I also have written many C run-time initializations. Simply, you have .data and a .bss segments for variables (we'll ignore code, .text, for now). The BSS vars., those not given a compile time value, are collected and the linker records the start address and size in linker generated constants. Then it collects all the .data vars., those with compile time initial values, and places them into the image. The .data start and size is also recorded for run-time relocation. The C run-time knows the names of the linker generated labels and memsets .bss to zero if the size is non-zero and copies .data to its run-time address if the address is different and the size is non-zero. Given this, the _at_ directive essentially creates a new, "non-standard" section which the C run-time does not know about. Could it? Yes. But it may complicate a well proven C51 C run-time just to allow people to place regular memory varables at certain locations with an initial value. A possible solution. When using _at_ the compiler puts the variable into new .atdata and .atbss sections depending upon their compile time init. value (if any). Then the linker would create atypical section start/size variables for the .atdata and .atbss sections. Finally, we'd all modify our C startup asm routine to memset or memcpy these sections appropriately. - Mark
To Mark Odell "I ask why? Why do you need a variable at a particular address? " Have you not heard of memory-mapped I/O, I rarely use nothing but. Erik
I have heard of memory mapped I/O and I use _at_ for just that. However, I never want the C run-time to write initial values to it! Do you? If the lcdControlReg is located at 0x8000 what does it mean to give it an initial value of 5? Why would it be better to have the C run-time do this for you than simply doing it explicitly? - Mark
I now see that you mis-understood me. I didn't ask why one would want a memory mapped address at a particular address. I asked why you'd want a *variable* at a particular address. A variable here means plain old program data, *not* memory mapped hardware object. Didn't you read the rest of the post? - Mark
Mark wrote: "I asked why you'd want a *variable* at a particular address." As I said, judging by the number of times the question gets asked here, there's a lot of people who do want to do it! They don't usually say why they want to do it, so it's hard to say whether they have good reasons! I agree that it's probably not wise to rely on the 'C' runtime to initialise your memory-mapped peripherals, but I can think of 2 applications where an _at_ with an initialiser seems reasonable: 1. Cases such as the original post here, where some configuration values need to be set in a specific location - especially if it's in ROM; 2. To place some sort of "signature" (eg, version info) into a known location in ROM.
1. Cases such as the original post here, where some configuration values need to be set in a specific location - especially if it's in ROM; I think that this is best handled in the startup code along with the reset of the chip initialization. Jon
Andrew wrote: As I said, judging by the number of times the question gets asked here, there's a lot of people who do want to do it! They don't usually say why they want to do it, so it's hard to say whether they have good reasons! True, so let's show them alternatives that they can have now. For case 1: For the ROM case linker will create an image size large enough to capture the _at_ address. On a 64kB ROM this may not pose a real problem, but in principle I don't like padding out my image (.bin) just to get up to the checksum value up at 0xFFFE. What if I have to download this upgrade image over a slow link? For the RAM case, be explicit and just do it at run-time. I, again, stipulate that no one in their right mind would allow some memcpy routine to initialize memory mapped I/O addresses in XDATA. As for case 2: We really need to get comfortable with .a51 files. :-) - Mark