|
|
 | | From: | Peng | | Subject: | Help needed for C/C++ programming for ARM evaluation board | | Date: | Fri, 07 Jan 2005 11:49:18 +0000 |
|
|
 | Dear all, I would like to program the ARM evaluation board with C++. I have some experience with the ARM assembler. - Do I need to set some compiler directives or constants in the program code? - I need to access memory addressed hardwares. Can I do this with pointers in the normal way?
Thank you very much!
Peng
|
|
 | | From: | Paco M | | Subject: | Re: Help needed for C/C++ programming for ARM evaluation board | | Date: | Fri, 07 Jan 2005 14:59:53 +0100 |
|
|
 | >Dear all, >I would like to program the ARM evaluation board with C++. I have some >experience with the ARM assembler. >- Do I need to set some compiler directives or constants in the program >code? The directives are the usual for any program in C/C++, but the important thing is the linker, you should read the manual to how to place the object code in memory, in the GNU gcc usually is made in the file my_code.vct to control the linker use >- I need to access memory addressed hardwares. Can I do this with >pointers in the normal way?
yes, but you should define the pointer as "volatile ..."
> >Thank you very much! > >Peng
|
|
 | | From: | Rainer Weikusat | | Subject: | Re: Help needed for C/C++ programming for ARM evaluation board | | Date: | Fri, 07 Jan 2005 15:57:03 +0100 |
|
|
 | Paco M writes: >>I would like to program the ARM evaluation board with C++. I have some >>experience with the ARM assembler. >>- Do I need to set some compiler directives or constants in the program >>code? > The directives are the usual for any program in C/C++, but the > important thing is the linker, you should read the manual to how to > place the object code in memory, in the GNU gcc usually is made in the > file my_code.vct to control the linker use
The GNU C-Compiler will pass any file it does not recognize as source code to be compile unchanged to the linker and if that happens to be the GNU linker, it will interpret (or try to interpret) non-object files as linker scripts, which in turn can be used to specify the intended memory layout for the resulting binary. An extremely simple example:
/* linker script for flasher */
SECTIONS { . = 0x8000000; .ipc : { *(.ipc) } .text : { *(.text) } .stack : { *(.stack) } .data : { *(.data) } .rodata : { *(.rodata) } }
The name doesn't matter ;-).
|
|
 | | From: | Peng | | Subject: | Re: Help needed for C/C++ programming for ARM evaluation board | | Date: | Fri, 07 Jan 2005 16:19:14 +0000 |
|
|
 | Rainer Weikusat wrote:
> Paco M writes: > >>>I would like to program the ARM evaluation board with C++. I have some >>>experience with the ARM assembler. >>>- Do I need to set some compiler directives or constants in the program >>>code? >> >>The directives are the usual for any program in C/C++, but the >>important thing is the linker, you should read the manual to how to >>place the object code in memory, in the GNU gcc usually is made in the >>file my_code.vct to control the linker use > > > The GNU C-Compiler will pass any file it does not recognize as source > code to be compile unchanged to the linker and if that happens to be > the GNU linker, it will interpret (or try to interpret) non-object > files as linker scripts, which in turn can be used to specify the > intended memory layout for the resulting binary. An extremely simple > example: > > /* > linker script for flasher > */ > > SECTIONS > { > . = 0x8000000; > .ipc : { *(.ipc) } > .text : { *(.text) } > .stack : { *(.stack) } > .data : { *(.data) } > .rodata : { *(.rodata) } > } > > The name doesn't matter ;-). Thank you very much. However, could you point to me where I can find more info about the SECTIONS? Thank you.
|
|
 | | From: | Tauno Voipio | | Subject: | Re: Help needed for C/C++ programming for ARM evaluation board | | Date: | Fri, 07 Jan 2005 18:09:45 GMT |
|
|
 | Peng wrote:
> Thank you very much. > However, could you point to me where I can find more info about the > SECTIONS? > Thank you.
A section is a part of the program addressing range. It is a tool to direct the different memory areas of a module to proper places to memory.
The assembler (itself or as last stage of compilation) puts diffrerent parts of the programs address space into different sections. The addresses in each section are counted from the relative zero address, so in a module sections are separate pieces of memory.
Classically, the C code is split into 3 sections:
- .text, containing code and constant data, - .data, containing initialized data, and - .bss, containing uninitialized data.
The run-time system uses at least a fourth section for the stack. There may be other sections, as the run-time library writers feel suitable.
The linker combines parts of sections from all modules to combined sections in the output file, and optionally assigns addresses to the sections.
This is the stage where the addresses of different items in memory are determined.
For sectioning in GNU tools, get the binutils manuals from , and read the information in the as (assembler) and ld (linker) manuals.
In the GNU ld, the section combining and address allocation process can be controlled in a very detailed way by writing custom linker scripts.
For stand-alone code (including embedded code), it is usually necessary to tailor a linker script for the target hardware.
HTH
--
Tauno Voipio tauno voipio (at) iki fi
|
|
 | | From: | Peng | | Subject: | Re: Help needed for C/C++ programming for ARM evaluation board | | Date: | Fri, 07 Jan 2005 16:17:34 +0000 |
|
|
 | Paco M wrote:
Thank you for helping. >>Dear all, >>I would like to program the ARM evaluation board with C++. I have some >>experience with the ARM assembler. >>- Do I need to set some compiler directives or constants in the program >>code? > > The directives are the usual for any program in C/C++, but the > important thing is the linker, you should read the manual to how to > place the object code in memory, in the GNU gcc usually is made in the > file my_code.vct to control the linker use > >>- I need to access memory addressed hardwares. Can I do this with >>pointers in the normal way? > > > yes, but you should define the pointer as "volatile ..." >
What is "volatile"? Sorry I don't understand how to do it. Thanks. Peng
|
|
 | | From: | Peng | | Subject: | Re: Help needed for C/C++ programming for ARM evaluation board | | Date: | Fri, 07 Jan 2005 16:46:36 +0000 |
|
|
 | Peng wrote:
> Paco M wrote: > > Thank you for helping. > >>> Dear all, >>> I would like to program the ARM evaluation board with C++. I have >>> some experience with the ARM assembler. >>> - Do I need to set some compiler directives or constants in the >>> program code? >> >> >> The directives are the usual for any program in C/C++, but the >> important thing is the linker, you should read the manual to how to >> place the object code in memory, in the GNU gcc usually is made in the >> file my_code.vct to control the linker use >> >>> - I need to access memory addressed hardwares. Can I do this with >>> pointers in the normal way? >> >> >> >> yes, but you should define the pointer as "volatile ..." >>
Sorry I was lazy. Now I understand volatile.
|
|
 | | From: | Paco M | | Subject: | Re: Help needed for C/C++ programming for ARM evaluation board | | Date: | Tue, 11 Jan 2005 08:51:36 +0100 |
|
|
 | the volatile are a definition of a variable that force to compiler to create
use
main() { /* the pointer anychar could exist or not */ char *anychar;
/* In ALL cases point_to_memory will exist in memory */ volatile char *pointer_to_memory; ............................................. pointer_to_memory = 0x0000000F; /* Now *pointer_to_memory is place exactly in the position 0x0000000F */ .................................................
}
On Fri, 07 Jan 2005 16:46:36 +0000, Peng wrote:
>Peng wrote: > >> Paco M wrote: >> >> Thank you for helping. >> >>>> Dear all, >>>> I would like to program the ARM evaluation board with C++. I have >>>> some experience with the ARM assembler. >>>> - Do I need to set some compiler directives or constants in the >>>> program code? >>> >>> >>> The directives are the usual for any program in C/C++, but the >>> important thing is the linker, you should read the manual to how to >>> place the object code in memory, in the GNU gcc usually is made in the >>> file my_code.vct to control the linker use >>> >>>> - I need to access memory addressed hardwares. Can I do this with >>>> pointers in the normal way? >>> >>> >>> >>> yes, but you should define the pointer as "volatile ..." >>> > >Sorry I was lazy. Now I understand volatile.
|
|
 | | From: | Peng | | Subject: | Re: Help needed for C/C++ programming for ARM evaluation board | | Date: | Tue, 11 Jan 2005 15:37:42 +0000 |
|
|
 | Paco M wrote:
> the volatile are a definition of a variable that force to compiler to > create > > use > > main() > { > /* the pointer anychar could exist or not */ > char *anychar; > > /* In ALL cases point_to_memory will exist in memory > */ > volatile char *pointer_to_memory; > ............................................ > pointer_to_memory = 0x0000000F; /* Now *pointer_to_memory is > place exactly in the position 0x0000000F */ > ................................................ > > } Thank you for pointing out.
|
|
 | | From: | Rainer Weikusat | | Subject: | Re: Help needed for C/C++ programming for ARM evaluation board | | Date: | Sat, 08 Jan 2005 15:31:23 +0100 |
|
|
 | Tauno Voipio writes:
[...]
> Classically, the C code is split into 3 sections: > > - .text, containing code and constant data,
When using gas directly, it's better not to mix code and constant data, because that may cause sequences of code to start at adresses that are not word aligned, which the assembler will silently ignore, except insofar as it would otherwise need to emit branches to invalid addresses. The actual branch target will be a valid address somewhere near the location of the intended branch target. Not only does this result in funnily behaving machine code, but it may additionally confuse people trusting their tools enough to not check the actual output.
|
|
 | | From: | Tauno Voipio | | Subject: | Re: Help needed for C/C++ programming for ARM evaluation board | | Date: | Sun, 09 Jan 2005 16:56:54 GMT |
|
|
 | Rainer Weikusat wrote: > Tauno Voipio writes: > > [...] > > >>Classically, the C code is split into 3 sections: >> >> - .text, containing code and constant data, > > > When using gas directly, it's better not to mix code and > constant data, because that may cause sequences of code to start at > adresses that are not word aligned, which the assembler will silently > ignore, except insofar as it would otherwise need to emit branches to > invalid addresses. The actual branch target will be a valid address > somewhere near the location of the intended branch target. Not only > does this result in funnily behaving machine code, but it may > additionally confuse people trusting their tools enough to not check > the actual output.
An assembler programmer should understand to use the align directive.
The addressing structure of an ARM forces the inclusion of address constants into the .text section.
--
Tauno Voipio tauno voipio (at) iki fi
|
|
 | | From: | Rainer Weikusat | | Subject: | Re: Help needed for C/C++ programming for ARM evaluation board | | Date: | Mon, 10 Jan 2005 21:09:27 +0100 |
|
|
 | Tauno Voipio writes: > Rainer Weikusat wrote: >> Tauno Voipio writes:
[...]
>>>An assembler programmer should understand to use >>>the align directive. >> Which would be 'not at all' in this case, because there's not much of >> a point in inserting waste octets in front of functions just for the >> sake of doing so. This doesn't make the assembler any less >> misbehaving, though. > > Please read the description of the align directive again: > there are no wasted octets if the location counter is > already aligned.
Ok ... apparently I must express this a lot simpler ...
An ARM instruction has 32 bit. ARM instructions must be word aligned in memory for the core to be able to execute them. As each of this instruction has the size of a word, this is naturally the case for any instruction in a sequence of instructions that started at an address that was word aligned. By inserting constant data into .text, specifically, string constants, it is possible that the start address of a subsequent instruction sequence is no longer word aligned. This could be cured by prefixing each instruction sequence with .align 2. This directive causes the lower two bits of the location counter to be zero, meaning its value is divisible by four. To do this, the value of the location counter at the point of the directive must be *advanced* to the next value that is divisble by four. The net effect of this is the insertion of 1 - 3 bytes without any function into the resulting object file. This (small) waste can be avoided by not keeping string constants in .text, but in some other section.
Apart from that, a program that cannot do something sensible with the input it has to process should not do something nonsensical instead.
[ manual omitted ]
> It is possible to use some of the shorter forms (immediate > data or pc addition)
Due to the fact that all ARM instructions have the same size (see above), which, by the way, is the reason for the range limits on certain immediate operandes, there are no 'shorter forms'. Neither immediate load (mov rN, #constant) nor pc addition (add rN, r15, #constant) have to access memory, therefore, they are faster than a pre-indexed indirect load (ldr rN, [r15, #constant]).
[...]
> In the general case when the target is not in the text > section of the current module and near enough, the translator > has to store the value (constant data) in the text section > outside the code flow. So, the architecture forces to > store constants in the text section.
The fact that this particular translator does store constant values that cannot be loaded into a register by mov, because the immediate operand of mov rN, #constant is limited to numbers that can be generated by rotating an eight-bit quantity by an even number of positions (which has exactly nothing to do with 'addressing', but is an artefact of this particular instruction encoding), alongside the code in no way implies a 'must'.
|
|
 | | From: | Tauno Voipio | | Subject: | Re: Help needed for C/C++ programming for ARM evaluation board | | Date: | Tue, 11 Jan 2005 22:02:50 GMT |
|
|
 | Rainer Weikusat wrote: > >>In the general case when the target is not in the text >>section of the current module and near enough, the translator >>has to store the value (constant data) in the text section >>outside the code flow. So, the architecture forces to >>store constants in the text section. > > > The fact that this particular translator does store constant values > that cannot be loaded into a register by mov, because the immediate > operand of mov rN, #constant is limited to numbers that can be > generated by rotating an eight-bit quantity by an even number of > positions (which has exactly nothing to do with 'addressing', but is > an artefact of this particular instruction encoding), alongside the > code in no way implies a 'must'.
OK.
Let's do it simple:
We need to access a variable from the .data section. Let's call it var. To do so, we first need to load tha address of the variable to an auxiliary register and then load the variable value:
adr r1,var ldr r0,[r1]
As the variable is not in .text section there is *no way* the translator could load the address as either an immediate data or a pc offset. There is no guarantee that .text and .data sections can be located within the reach of the pc offset.
If the code is in ROM and data in RAM, it is never possible to access an item in the .data section (RAM) directly from .text section (ROM) with the current memory chip sizes.
So the translation will be:
ldr r1,[pc, #offset] ldr r0,[r1]
----
ptr: dw var
where the offset from pc points to ptr. This construction *is* actually a two-word immediate load with the parts separated so that the program flow does not need to skip the contant in-line. The full-word constant is forced to be located into the .text section to be addressable at all.
This phenomenon is not an artefact, it is a basic property of a RISC processor. If the address width is the same as the data bus width, there is no way to squeeze an opcode and a full adddress into a single-word instruction.
--
Tauno Voipio tauno voipio (at) iki fi
|
|
 | | From: | Wilco Dijkstra | | Subject: | Re: Help needed for C/C++ programming for ARM evaluation board | | Date: | Wed, 12 Jan 2005 00:06:02 GMT |
|
|
 | "Tauno Voipio" wrote in message news:e2YEd.711$HJ5.669@read3.inet.fi... > Rainer Weikusat wrote:
> > The fact that this particular translator does store constant values > > that cannot be loaded into a register by mov, because the immediate > > operand of mov rN, #constant is limited to numbers that can be > > generated by rotating an eight-bit quantity by an even number of > > positions (which has exactly nothing to do with 'addressing', but is > > an artefact of this particular instruction encoding), alongside the > > code in no way implies a 'must'. > > OK. > > Let's do it simple: > > We need to access a variable from the .data section. > Let's call it var. To do so, we first need to load > tha address of the variable to an auxiliary register > and then load the variable value: > > adr r1,var > ldr r0,[r1] > > As the variable is not in .text section there is > *no way* the translator could load the address as > either an immediate data or a pc offset. There is > no guarantee that .text and .data sections can > be located within the reach of the pc offset.
Rainer means there are lots of different ways of creating an address:
1. Using a literal pool stored in the .text section 2. Creating the address using several ADD instructions 3. Using a register pointing to the start of a pool containing literals 4. Using a register pointing to the start of a (small) data section 5. Combine 2 and 4 to create a larger range 6. Placing .data sections close to .text sections so they are in range
All of these are used in practice. (2) is feasible in Thumb-2 using only 2 instructions rather than 4, (4) and (5) were(?) used in an ARM compiler. I've used (3) and (6) when writing assembler. Other RISC architectures use (4), (5), (2), or (3) plus (4).
PC-relative addressing is often lacking on RISCs, so few use (1). However it is the clear winner on ARM as it allows fast access to literals in a single instruction, while allowing sharing of the literals across several functions. If ARM had a few more registers and slightly larger offsets in loads and stores it may have been better to use (4) or (5) like most RISCs.
Wilco
|
|
 | | From: | Tauno Voipio | | Subject: | Re: Help needed for C/C++ programming for ARM evaluation board | | Date: | Wed, 12 Jan 2005 09:07:57 GMT |
|
|
 | Wilco Dijkstra wrote: > Rainer means there are lots of different ways of creating an address: > > 1. Using a literal pool stored in the .text section > 2. Creating the address using several ADD instructions > 3. Using a register pointing to the start of a pool containing literals > 4. Using a register pointing to the start of a (small) data section > 5. Combine 2 and 4 to create a larger range > 6. Placing .data sections close to .text sections so they are in range > > All of these are used in practice. (2) is feasible in Thumb-2 using > only 2 instructions rather than 4, (4) and (5) were(?) used in an ARM > compiler. I've used (3) and (6) when writing assembler. Other RISC > architectures use (4), (5), (2), or (3) plus (4). > > PC-relative addressing is often lacking on RISCs, so few use (1). > However it is the clear winner on ARM as it allows fast access to > literals in a single instruction, while allowing sharing of the literals > across several functions. If ARM had a few more registers and slightly > larger offsets in loads and stores it may have been better to use (4) > or (5) like most RISCs. >
Rainer started the discussion, when I tried to keep the GCC sectioning explanation simple and said that the ..text section contains code and constant data. It is not shown that this is incorrect (though not accurate, intentionally, to keep the OP response simple).
The methods other than 1. above will produce rashes to the linker, and it pretty often leads to undefined length of code after assembly (or extra nop's).
The method 2. does not reach the full memory range in Thumb mode - the offsets are not large enough.
In many cases 6. is out of question. A good example is the Atmel evaluation board, having the on-chip RAM at 0 - 0x3ffff and ROM starting at 0x01000000. If .text (and .rodata) is in ROM and .data in RAM, the case is obviously impossible.
The method 3. is essentially the same as 1., with the extra cost of the literal base register. In the ARM, the base register comes free as the PC.
The method 4. loses an extra register without giving any advantage on an ARM.
It is pretty clear that the method 1. is the way to go with an ARM. The thing is clearly mentioned in the ARM ARM (Architecture Reference Manual).
I think that we're actually having a common idea of the addressing problem, and it may be the time to close this thread. Thanks for the discussion.
--
Tauno Voipio tauno voipio (at) iki fi
|
|
 | | From: | Rainer Weikusat | | Subject: | Re: Help needed for C/C++ programming for ARM evaluation board | | Date: | Sun, 09 Jan 2005 18:58:51 +0100 |
|
|
 | Tauno Voipio writes: > Rainer Weikusat wrote: >> Tauno Voipio writes: >> [...] >> >>>Classically, the C code is split into 3 sections: >>> >>> - .text, containing code and constant data, >> When using gas directly, it's better not to mix code and >> constant data, because that may cause sequences of code to start at >> adresses that are not word aligned, which the assembler will silently >> ignore, except insofar as it would otherwise need to emit branches to >> invalid addresses. The actual branch target will be a valid address >> somewhere near the location of the intended branch target. Not only >> does this result in funnily behaving machine code, but it may >> additionally confuse people trusting their tools enough to not check >> the actual output. > > An assembler programmer should understand to use > the align directive.
Which would be 'not at all' in this case, because there's not much of a point in inserting waste octets in front of functions just for the sake of doing so. This doesn't make the assembler any less misbehaving, though.
> The addressing structure of an ARM forces the > inclusion of address constants into the .text > section.
The limitations of immediate operands to a certain form of the MOV instruction, combined with the availability of a specific gas-'pseudo instruction' make it convenient to have address constants (which, by the way, cannot cause misalignments) close enough to the pc to load them from there. But nothing 'forces' you to do that.
|
|
 | | From: | Tauno Voipio | | Subject: | Re: Help needed for C/C++ programming for ARM evaluation board | | Date: | Mon, 10 Jan 2005 07:45:30 GMT |
|
|
 | Rainer Weikusat wrote: > Tauno Voipio writes: > >>Rainer Weikusat wrote: >> >>>Tauno Voipio writes: >>>[...] >>> >>> >>>>Classically, the C code is split into 3 sections: >>>> >>>> - .text, containing code and constant data, >>> >>>When using gas directly, it's better not to mix code and >>>constant data, because that may cause sequences of code to start at >>>adresses that are not word aligned, which the assembler will silently >>>ignore, except insofar as it would otherwise need to emit branches to >>>invalid addresses. The actual branch target will be a valid address >>>somewhere near the location of the intended branch target. Not only >>>does this result in funnily behaving machine code, but it may >>>additionally confuse people trusting their tools enough to not check >>>the actual output. >> >>An assembler programmer should understand to use >>the align directive. > > > Which would be 'not at all' in this case, because there's not much of > a point in inserting waste octets in front of functions just for the > sake of doing so. This doesn't make the assembler any less > misbehaving, though. >
Please read the description of the align directive again: there are no wasted octets if the location counter is already aligned.
>>The addressing structure of an ARM forces the >>inclusion of address constants into the .text >>section. > > > The limitations of immediate operands to a certain form of the MOV > instruction, combined with the availability of a specific gas-'pseudo > instruction' make it convenient to have address constants (which, by > the way, cannot cause misalignments) close enough to the pc to load > them from there. But nothing 'forces' you to do that.
The architecture-imposed addressing limitation stays there, regardless whether the code is generated directly or by an assembler pesudo-op.
You seem to refer to the
adr reg,address
and
ldr reg,=constant
constructions. The former is a pseudo-operation which translates either to an addition to pc or a form of the latter.
The latter is a literal load which translates to either an immediate load or an indirect load with a pc offset.
It is possible to use some of the shorter forms (immediate data or pc addition) if the final offset is known at the assembly stage. This requires that the constant to load is absolute and some of the immediately loadable values or the target address is in the code section near enough to be addressed directly with pc offset.
In the general case when the target is not in the text section of the current module and near enough, the translator has to store the value (constant data) in the text section outside the code flow. So, the architecture forces to store constants in the text section.
Look at the code generated by GCC with the switches
gcc -S -O2 myfile.c
and have a look at the embedded constanst.
I left out intentionally the extra sections generated by modern compilers. For example, GCC generates the section .rodata for constants not forced to reside in the code section, and separate sections for constant strings.
I hope this clarifies my position.
Tauno Voipio tauno voipio (at) iki fi
|
|
 | | From: | Rainer Weikusat | | Subject: | Re: Help needed for C/C++ programming for ARM evaluation board | | Date: | Wed, 12 Jan 2005 11:58:05 +0100 |
|
|
 | Tauno Voipio writes: > Rainer Weikusat wrote: >>>In the general case when the target is not in the text >>>section of the current module and near enough, the translator >>>has to store the value (constant data) in the text section >>>outside the code flow. So, the architecture forces to >>>store constants in the text section. >> The fact that this particular translator does store constant values >> that cannot be loaded into a register by mov, because the immediate >> operand of mov rN, #constant is limited to numbers that can be >> generated by rotating an eight-bit quantity by an even number of >> positions (which has exactly nothing to do with 'addressing', but is >> an artefact of this particular instruction encoding), alongside the >> code in no way implies a 'must'. > > OK. > > Let's do it simple:
[third explanation of how gcc moves 32 bit constants into ARM registers]
Would you be so kind to stop 'explaining' stuff that everybody understands at least as well as you do over and over again?
|
|
|