When you use Embest IDE to debug B0, you want to operate internal registers in the C environment. I checked a lot of information, but the compilation was always fail. According to the _ ASM format in the book, it is still wrong. Later, after one day and one night of hard work, we finally achieved it. Now, let's take a look at it ~~
On the Internet, we are talking about 80x86 embedded assembly, which is not compatible with the above format. The syntax of arm-elf-GCC and arm-Linux-GCC is also different.
At the beginning, I saw a debugging note written by a renxiong on the Internet. He said he had no money to buy a simulator and could only burn the program. He is debugging with ads. To see the internal registers (R0-R15) level, you must read these registers and then observe them through the serial port. However, it is impossible to operate internal registers in the C environment, and assembly can only be embedded in C.
I used Embest IDE, because the examples are all in the GCC environment, so I used this environment for debugging. At the beginning, I copied the brother program above, I found that the syntax in the two environments was completely different after I wrote a sentence, so I went to the evening to find an example. The following is the code of this guy. It may be applicable to ADS (not tested)
Int readpc (INT argc, char * argv [])
{
U32 I;
2010j, K;
_ ASM
{
MoV I, R15
}
J = I/0x10000;
K = I % 0x10000;
Printf ("PC value = 0x % x/N", I );
Printf ("PC value = % d-% d/N", j, k );
_ ASM
{
Mrs I, CPSR
}
J = I/0x10000;
K = I % 0x10000;
Printf ("CPSR value = 0x % x/N", I );
Printf ("CPSR value = % d-% d/N", j, k );
Return 0;
}
There is an example in the book, but there is only one sentence:
_ ASM ("mov r0, R0 ");
I wrote this sentence and compiled it. I thought it was done. But next I encountered another problem: how can I pass the register value to the variable in C? I also tried to directly use the variable mov I in the Assembly, and r15 returned an error.
Then, someone on csdn said: Define int get_r0 (void ){}
Then call int I = get_r0;
I guess it's not possible, but the fact is that it actually got the R0 value. At first I thought it was different. I thought get_r0 () was a library function. I changed R0 to R15, the strange result is that the obtained value is R0. The result of changing get_r0 to MM _ R0 can still be the R0 value. Although I don't understand why, I changed the program to my goal. Use _ ASM ("mov r0, R15") before int I = get_r0; so that the R15 is the Pc value. I watched my cell phone go to bed three and a half in the morning.
The next morning, I started up early. After a few hours of exploration, I accidentally found that LDR R1, = I was correct. It's great to finally link it with C. Now it's easy to do it. Just give the R15 value to R0 and then STR r0, [R1] so that the R15 value is assigned to the variable.
_ ASM ("LDR R1, = I
MoV r0, R15
STR r0, [R1]
")
Compile, link, and run. The serial port does not respond. Fortunately, I have a simulator. I found an undefined command exception during single-step debugging. The program jumped to 0x00000004. When I opened the Assembly window, I found that there was another unknown thing behind these commands:
0x0c0019a4 stfeqd F3, [R0],-#800
When I delete all statements, this statement will still appear, that is, as long as _ ASM is used.
Every time I run it here, an exception occurs, so I changed the program to this: Run, and the result shows the Pc value completely:
_ ASM ("ldmfd sp, {r0, R1}
LDR R1, = mr15
MoV r0, R15
Sub r0, R0, #0x16 // restore the current Pc value
STR r0, [R1]
Stmfd SP !, {R0, R1}
Add PC, PC, #0x01 // to skip the undefined command
");
Uart_printf ("/NPC = 0x % x/N", mr15); this section is intended to be defined as a macro and will be expanded directly later. However, the _ ASM format is too harsh and fails. But it should be possible to wrap it into a function, then directly read the LC-8 is the value of PC ....