C- Syntax to allocate Global variables to consecutive memory locations

Hello all

I'm a fresher to Microcontroller programming. I have defined certain global variables that I need to store at consecutive memory locations, say starting from 0x8000h . Will appreciate if anyone can list the syntax / instructions to go about the same.

thanks

techie

Reply to
techie.embedded
Loading thread data ...

This is not a feature of standard C. Some C compilers for embedded platforms have their own proprietary methods of doing this sort of thing. In other cases you might have to resort to declaring variables in an assembly language source file to ensure they appear at a known memory location.

In some cases, you can rely on known behaviour of a specific compiler so that a particular order of variable declaration will result in a particular memory layout.

In any case, you might need to give special instructions to the linker to reserve a memory area for an unusual purpose.

None of these mechanisms are portable to other platforms or compilers.

What microprocessor and compiler/toolchain are you using?

--
David Empson
dempson@actrix.gen.nz
Reply to
David Empson

One way (rather awkward, but works) would be to address them entirely via pointers: eg typedef volatile int* pInt; pInt my1 = 0x8000; pInt my2 = 0x8004; // Strictly, 0x8000 + sizeof(int) ...

Reply to
David R Brooks

Byte Craft's compilers have a language extension that allows defininng the location of variables.

int abc @ 0x123;

for example.

w..

-- Walter Banks Byte Craft Limited

formatting link

Reply to
Walter Banks

Well, I'm using the Code composer studio from Texas Instruments. So, do u then suggest that I carry out those routines in Assembly only ???

Also, is the method of using Pointers like suggested above safe ??? what sort of awkardness would that be causing to my program ???

thanks

techie

Reply to
techie.embedded

Techie, you might want to take a look at your keyboard - it looks like your question mark key is a little sticky.

Deep.

Reply to
Deep Reset

  1. Declare a section at the desired memory location in the linker file.
  2. Declare your variables as an array or structure in that section in C code.

Vladimir Vassilevsky

DSP and Mixed Signal Design Consultant

formatting link

Reply to
Vladimir Vassilevsky

The fields of a struct will be laid down in memory in the order they are declared, e.g.,

struct { int first; int second; char third; int fourth; } Contiguous;

declares a variable named Contiguous with four fields (first, second, third, and fourth), such that &Contiguous.first < &Contiguous.second < &Contiguous.third < Contiguous.fourth. However, there may be some padding bytes between fields (particularly between third and fourth, though it could be between first and second as well, depending on the implementation's alignment requirements).

Locating the variable Contiguous at, say, 0x8000 is the job of the linker rather than the compiler.

Regards,

-=Dave

Reply to
Dave Hansen

Not necessarily. See Vladimir Vassilevsky's reply later in the thread. I am just expanding his response.

Many of the cross compilers for embedded systems allow you to define memory sections. These definitions usually go into the linker control files. If your tool chain comes with an IDE, it will usually allow you to define it using the IDE without having to modify the linker control files directly. You can specify the memory range and a name for the section. Please note that the tool chain will have some predefined sections. Ensure that your definitions do not conflict with these. The compiler will provide a proprietary extension (perhaps using pragma directives) to specify that a variable belongs to a section. If you define more variables than that could be accommodated in the section, you usually get a linker error.

If you want to make sure that the variables are located in a specific order, you have two options as pointed out by Vladimir.

1) If all the variables are of the same type, use an array. If you want to refer to individual variables by name (and not an array index), declare pointers to them. 2) If the variables are of different types, use a structure and declare the variables in the order in which you want them to be stored. You have to make sure that the structure padding is acceptable. Most cross compilers allow you to specify the padding. Once the structure is defined, declare a variable of this structure type and put it in the section.

If you are referring to the post by David R Brooks, the method would work in many cases. However, you may run into problems with the linker allocating other variables at this location. I strongly recommend against that approach especially if you are new to embedded programming.

These are a few directions to get you started. There are many other issues that might come up later. Refer the documentation of your tool chain for the inner details.

Have a nice day, Pradeep

--
All opinions are mine and do not represent the views or
policies of my employer.
R Pradeep Chandran                 rpc AT pobox DOT com
Reply to
R Pradeep Chandran

Hi, Walter. Does this look like a storage request to the linker? Or does it merely create a symbolic linker value?

To put my question in exact context, one of the things I miss having in C and readily find with assembly coding (usually) is the ability to define link-time constants. By this, I mean the equivalent in x86 asm of:

_abc EQU 0x123 PUBLIC _abc

This places a symbolic value in the OBJ file that can be linked into other files and used as constant values. In c, I might use:

extern int abc; #define MYCONST (&abc)

and then refer to MYCONST throughout the c source. The result allows me to modify the constant definitions without requiring recompilation of the c sources. The link process is all that is required.

If your c compiler creates the object equivalent of a PUBDEF and an EXTDEF, but no LEDATA, from:

int abc @ 0x123;

That would be interesting.

I hope that sharpens my question.

Jon

Reply to
Jonathan Kirwan

Are you sure that's actually what you _need_ to do? As opposed to what you _want_ to do, that is?

Locating several data objects in defined sequence is what C gives you data structures for --- you shouldn't usually be trying to do that with individual variables, but with elements of a container data type.

Locating objects at absolute addresses is none of a C compiler's job, really. Which is why Standard C has no syntax to do it. That kind of work should be done either directly in assembler (because only assembler code habitually relies on such knowledge anyway), or by the linker.

Reply to
Hans-Bernhard Bröker

To be nitpickingly precise: no, that doesn't really work. There's no well-defined mapping from integers to pointers, so any code that casts an integer constant to a pointer type and proceeds to dereference that pointer exhibits undefined behaviour. Which is as far from "works" as one can possibly be and still _sometimes_ get a working program.

Reply to
Hans-Bernhard Bröker

Hi-Tech C's approach to this is very useful and works well; the compilers for many architectures include low-level constructs that in many cases avoid the need for assembly code and special link commands. It is common to specify absolute locations using the '@' modifier as in

static unsigned char int_mask @ 0x08;

Regards,

Michael

Reply to
msg

the module

Thanks, Stan. But this doesn't do what I said. Did you read me carefully?

Jon

Reply to
Jonathan Kirwan

Are you sure that only the link process is required. I think that you need to compile (or assemble) the file containing the declaration of abc (or _abc).

Have a nice day, Pradeep

--
All opinions are mine and do not represent the views or
policies of my employer.
R Pradeep Chandran                 rpc AT pobox DOT com
Reply to
R Pradeep Chandran

By this, I am referring to the two parts, the "Does this look like a storage request to the linker? Or does it merely create a symbolic linker value?" and the "no LEDATA" comments I made.

I'm asking about link-time constants which do NOT generate static storage.

Jon

Reply to
Jonathan Kirwan

This is what I also thought at first. This approach does require the compilation of the source file containing the constant.

However, when I thought more about it I found another problem with this approach. The compiler is not required to assign storage for the constant. It could replace it with a literal constant (similar to #define). Declaring it as volatile might help.

volatile const int abc = 0x123;

and

extern volatile const int abc;

Have a nice day, Pradeep

--
All opinions are mine and do not represent the views or
policies of my employer.
R Pradeep Chandran                 rpc AT pobox DOT com
Reply to
R Pradeep Chandran

It is not really an elegant solution. ISO/IEC 9899:1999 provides #pragma directive to handle such cases. In fact many compilers use this approach for implementation specific operations (Tasking compiler for example). This approach makes it easier to use tools like PCLint.

Have a nice day, Pradeep

--
All opinions are mine and do not represent the views or
policies of my employer.
R Pradeep Chandran                 rpc AT pobox DOT com
Reply to
R Pradeep Chandran

"Jonathan Kirwan" wrote

The way to use this is with the const keyward, in one module you have the line

const int abc = 0x123;

In the corresponding header file you have

extern const int abc;

then any module that includes the header fine can refer to the integer constant abc, and to change the value of abc you simply change the value in the module where it is defined (and assigned), recompile that module and re-link.

Stan Katz

Reply to
Stan Katz

Yes. Been there, done it.

In the example I gave, where I've used two source files -- one in assembly and one in c -- changing a constant value requires editing the assembly code and re-assembly of that file in order to produce the OBJ file, plus a link step to complete the executable.

My point was that there was no _c_ compilation required -- not that the file containing the constants didn't need re-assembly.

Normally, in c-only projects, the only type of symbolic named constant that doesn't require storage is found in the pre-processor's #define. If you change the value of such symbolic constants, all of the c source files which reference those constants must be recompiled by the c compiler.

In the example I gave, no c source file which references those constants need to be recompiled.

These kinds of constants are nothing new in object files. They've been in use for the 30+ years I've been programming and they existed in the linkers I've written in my long past. The current linkers required for c do this all the time, as well. The only problem is that there is no syntax in c specifically for this semantic.

People who can only think in terms of the higher level language semantics they are hand-fed, conflate the ideas I'm talking about. In c, for example, the language will only generate a link-time symbolic reference from a declaration where the definition is external to the module. And when it does so, it depends upon the linker to provide the actual value for that link-time symbol. The only other case with c is where the compiler generates a definition (and a declaration) of the object -- but that requires storage -- and in any case, it again allows the linker to actually fill in the symbolic value that replaces other symbolic references, once the linker is finished with placement. In the assembly language case I mentioned, the assembler is perfectly free to provide a link-time symbolic constant where the value is provided by the assembler and not by the linker's location process. This semantic ability is explicitly missing in c.

A possibly good way to handle this without changing the c standard (at least, not changing the behavior of resulting code) would be to follow how a smart c++ compiler and its linker might interpret Stan's example:

const int abc= 0x123;

In c, this is not only a declaration but also a definition. It creates storage for 'abc' and initializes it -- in other words, there exists an address where the value 0x123 is stored, at run-time. If you placed that into a common include file, used by a variety of c source files, you'd be in a peck of trouble as each compilation unit would provide separate definitions. If placed into a single c file for compilation, storage would be allocated when perhaps none would be required.

In c++, if my feeble recollection about it remains, it is possible for the c++ compiler to remove the storage (if the compiler and linker are able to determine than an address reference is never required) and simply replace the value. I have one central problem in talking about c++: I don't use c++ in my embedded work. I also don't know of any embedded c++ compilers and linker combinations that achieve this, in practice. But even if they existed it wouldn't change my question regarding c.

Jon

Reply to
Jonathan Kirwan

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.