function pointers are the basis for implementing callback functions, which are the basis of C program architecture. So the importance of function pointers is self-evident. However, recently on the Arm Development Board test program, found that the function pointer can be compiled, but the runtime is always error. The following is one of the simplest test program source code.
static void Test ()
{
puts ("test\n");
}
static void (*f) = test;
void Main (void)
{
led_init ();
Key_init ();
Io_init (0);
f ();
while (1) {
puts ("-------Hello from main ()----------\ n");
Delay (100000);
}
The assembly code compiled using GCC-S is as follows:
. CPU Arm10tdmi. Eabi_attribute, 1 Eabi_attribute, 1 Eabi_attribute, 3 Eabi_attribute 24, 1 . Eabi_attribute, 1 Eabi_attribute, 2 eabi_attribute 6 eabi_attribute, 0 Eabi_attribu Te 4. File "MAIN.C". Section. Rodata. Align 2. LC0:. ASCII "test\012\000". Text. Align 2. syntax unified. arm. FPU softvfp. Type test,%f
Unction Test: @ args = 0, pretend = 0, frame = 0 @ frame_needed = 1, Uses_anonymous_args = 0 Push {FP, LR} Add FP, SP, #4 Ldr r0,. L2 BL puts NOP pop {fp, PC}. L3:. Align 2. L2:. Word. LC0. Size test,.-test. Data. Align 2. Type F,%object. Size F, 4 F:. Word test. Sect Ion. Rodata. Align 2. LC1:. ASCII "-------Hello from Main ()----------\012\000". Text. Align 2. LC1:. ASCII "-------Hello from Main ()----------\012\000". Text. Align 2. gloBal main syntax Unified. The FPU SOFTVFP. Type Main,%function main: @ args = 0, pretend = 0, fram E = 0 @ frame_needed = 1, Uses_anonymous_args = 0 Push {FP, LR} add FP, SP, #4 bl led_init bl key _init mov r0, #0 bl Io_init LDR R3,. L6 LDR R3, [R3] BLX R3. L5:ldr R0,. L6+4 BL puts Ldr r0,. l6+8 BL delay B. L5. L7:. Align 2. L6:. Word f. Word. LC1. Word 100000. Size Main,.-main. Ident "GCC: (GNU) 6.2.0".
Gnu-stack, "",%progbits
When the function pointer is visible, it is compiled into a BLX instruction. This instruction is to jump and change the running state (arm and thumb switch). Obviously this compilation is wrong, but also ask the master to help analyze, in the end is where the problem.
Is there a special compilation parameter required?
Headache...
2016-12-20 Update:
The reason has been found, the key points are as follows:
GCC compiles absolute address calls (including function pointer calls) into BLX RN directives. The BX,BLX instruction is used for absolute jumps (B,BL for jumps) and goes to the address contained in the RN. In summary, X has two meanings: (1) Determines whether a arm/thum switch is made according to the minimum bit of RN 0. (2) can be absolute address jump.
s3c2440a's instruction concentration is not BLX, only BX. Therefore, the runtime will be invalid instruction error.
Solution Idea:
(1) for GCC to run the appropriate parameters to avoid generating BLX instructions. It is not clear what parameter options are required.
(2) Using undefined exception handler to simulate BLX instruction. This looks complicated and is actually very simple to implement, already implemented in v0.9.