Hello,
data char var; void (code * data fptr)(void); void fun(void) { var = 10; } void main(void) { fptr = fun; (*fptr)(); // OK! (*(fptr = fun))(); // This line generates bad code! (*(fptr = &fun))(); // OK! while (1); }
Genereted source file:
; .\main.SRC generated from: main.c ; COMPILER INVOKED BY: ; C:\C51\V8_17\C51\BIN\C51.EXE main.c BROWSE DEBUG OBJECTEXTEND SRC(.\main.SRC) NAME MAIN ?PR?fun?MAIN SEGMENT CODE ?PR?main?MAIN SEGMENT CODE ?DT?MAIN SEGMENT DATA EXTRN CODE (?C_STARTUP) EXTRN CODE (?C?ICALL) PUBLIC var PUBLIC fptr PUBLIC main PUBLIC fun RSEG ?DT?MAIN fptr: DS 2 var: DS 1 ; ; data char var; ; void (code * data fptr)(void); ; ; void fun(void) RSEG ?PR?fun?MAIN fun: ; SOURCE LINE # 5 ; { ; SOURCE LINE # 6 ; var = 10; ; SOURCE LINE # 7 MOV var,#0AH ; } ; SOURCE LINE # 8 RET ; END OF fun ; ; void main(void) RSEG ?PR?main?MAIN main: USING 0 ; SOURCE LINE # 10 ; { ; SOURCE LINE # 11 ; fptr = fun; ; SOURCE LINE # 12 MOV fptr,#HIGH (fun) MOV fptr+01H,#LOW (fun) ; (*fptr)(); // OK! ; SOURCE LINE # 13 MOV R2,fptr MOV R1,fptr+01H LCALL ?C?ICALL ; (*(fptr = fun))(); // This line generates bad code! ; SOURCE LINE # 14 MOV R6,fun MOV fptr,R6 MOV R7,fun+01H MOV fptr+01H,R7 MOV R2,AR6 MOV R1,AR7 LCALL ?C?ICALL ; (*(fptr = &fun))(); // OK! ; SOURCE LINE # 15 MOV R2,#HIGH (fun) MOV R1,#LOW (fun) MOV fptr,R2 MOV fptr+01H,R1 LCALL ?C?ICALL ?C0002: ; while (1); ; SOURCE LINE # 16 SJMP ?C0002 ; END OF main END
If I change
void (code * data fptr)(void);
to
void (* data fptr)(void);
everything is OK. Why?
Thanks.
Henri
This looks like a generic vs. memory specific pointer issue. I believe the tools expect a function pointer to contain a 3-byte generic value.
Try defining the function pointer without the "code" option. By specifying "code" as the pointer type, it only passes two bytes on to the library, for de-refrencing.
On the other hand, I'd question why Henri would put 'code' there to begin with?
The code modifier is redundant as the manual says: http://www.keil.com/support/man/docs/c51/c51_le_code.htm But the code modifier is not forbidden here. It shouldn't make any difference. This still looks like compiler bug.
"But it doesn't change the fact that what Henri describes looks very much like a compiler bug."
because of the 'restrictions' resulting from the '51 architecture function pointers are, at best, kludged into c for the '51.
Perhaps. But it doesn't change the fact that what Henri describes looks very much like a compiler bug.
- mike
.... that with any other architecture (that I have worked with) I have used function pointers when practical with no hesitation.
Erik
the simple solution: do not use function pointers.
Yes, it can be done, but require a lot of care, intervention and also a lot of processing time.
what is wrong with if (x) { y(): }
or switch (x) case y: z();
View all questions in Keil forum