I have a need to initialize the ARM registers of my ARM7TDMI development board to a specific values using inline assembly. For example currently I do something like the following :
#pragma ARM
void init(char * reg) {
__asm {
MOV R0,#0x0
MOV R1,#0x1
MOV R2,#0x2
MOV R3,#0x3
...
}
The idea is to closely control the contents of each of the registers here. I am using KEIL UVision 5 and it warns me that this may not be a smart thing to do . And looking at the debugger there is no guarantee that the initialization will happen as per my request. For example the value 0x2 maybe stored in register r12 instead of r2 as i requested in my inline assembly ..
a.c(102): warning: #1267-D: Implicit physical register R0 should be defined as a variable
Reading up on Keil documentation http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka11441.html it suggests using variable names. Something like this
{
int val2;
__asm
{
MOV val2,0xFFFF0000
MOV val,val,LSL #16
}
Well this is not good enough for me as I want precise control over my register contents. How is it possible to do ? Any ideas ?
Thanks
-
\$\begingroup\$ Can I ask what you seek to achieve by having control over register allocation? \$\endgroup\$Houston Fortney– Houston Fortney09/22/2015 10:38:22Commented Sep 22, 2015 at 10:38
-
\$\begingroup\$ @HoustonFortney i want to generate a checksum/verification value using the contents of all the registers (it will include the PC CPSR values as well). The value will be unique if the inputs are initialized in a certain way. Any change in the inputs will generate a wrong value. \$\endgroup\$rockstar– rockstar09/22/2015 10:49:54Commented Sep 22, 2015 at 10:49
-
3\$\begingroup\$ Maybe better do that totally in assembler (in a .ams file)? \$\endgroup\$Wouter van Ooijen– Wouter van Ooijen09/22/2015 11:24:53Commented Sep 22, 2015 at 11:24
-
\$\begingroup\$ To put Wouter's comment more strongly: If you need to control the state of all of the CPU registers, then you CANNOT use a C compiler, which uses most, if not all, of the registers for its own purposes. That's what all the warnings are about. You MUST do this in pure assembly -- perhaps as a function that you can call from C, but then you need to write your function so that it is compatible with the C runtime environment. \$\endgroup\$Dave Tweed– Dave Tweed09/22/2015 13:37:18Commented Sep 22, 2015 at 13:37
2 Answers 2
The IDE you're using, like most IDEs, automates initialization CPU to the lowest level. It is responsible for generating, for example, the content of the vector table.
Using a language of higher level than assembler, everything related to manipulation of registers and initialization is quite hidden, especially if enabled compiler optimizations.
I think you should write the critical code in assembler, to ensure the performance of the CPU. Perhaps the rest of your application can be developed at the highest level, having the low-level code as a library.
-
\$\begingroup\$ Yes that is exactly what i did finally,works well now :) \$\endgroup\$rockstar– rockstar11/05/2015 02:38:28Commented Nov 5, 2015 at 2:38
I use the following function in my code with uVision 4.70
__asm void SetPOWCON(
u16 u16POWCON) // POWCON register value
{
Z_PLL EQU 0xFFFF0400 // PLL base address
R_NUM EQU 0x12345678 // Random Number for Dummy Multiplication
LDR r3,=R_NUM // Load random number for multiplication
LDR r1,=Z_PLL // Load base address of PLL / POWCON related MMRs
MOV r2,#1 // POWKEY0 = 1
STR r2,[r1,#4]
STR r0,[r1,#8] // Set POWCON value
MOV r0,#0xf4 // POWKEY1 = 0xF4
STR r0,[r1,#0xc]
UMLAL r2,r0,r3,r1
BX lr
}