We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
When I set optimize(9,size) to a interrupt function, which should be optimize for "Common Block Subroutines", but it wasn't! All interrupt funtions contain following duplicate blocks(see BOLD):
PUSH ACC PUSH B PUSH DPH PUSH DPL PUSH DPH1 PUSH DPL1 PUSH DPS MOV DPS,#00H PUSH PSW MOV PSW,#010H ;Depend on using. LCALL MyFunc POP PSW POP DPS POP DPL1 POP DPH1 POP DPL POP DPH POP B POP ACC RETI
>erik: I believe that if you made my_func inline.. The interrupt function must locate on common area. My idea is to minimize the size of common area, so I did my real jobs on another function which could be located on normal banks (Bank0,1,..). I can save many code sizes, because my_func's codes will not duplicate on every bank (common area). >Oleg: Now could you imagine, where the MCU jumps to when executes RET? I could imagine, because everything is under control. You have point out that we should play carefully with stack area, and as I know, the preceding codes should be fine.
Sorry, I forgot reponse to Graham. 1. I did tell the compiler my wish: optimize(9,size). Maybe it's keil's policy for interrupt function as you mention. 2. Since my chip support dual pointer, and keil's documents said it will improve the performance of may library functions, so I use it! In fact, I will use NOMODDP2 on those ISR functions (I have verify those ISRs won't call any improved functions), then, the extra code will be "PUSH DPS, and MOVE DPS,#0" which takes only 5 machin cycles. The extra latency is fine for my project.
No, it will not work in the whole. In your example, when RET command of LB1() executes, MCU jumps to random address (in fact it goes to address given from two last bytes on the stack). See once again: LCALL LB1 puts return address (address of the next command after LCALL) on the top of stack. Inside your LB1() routine there are some PUSHes which increase stack pointer for each byte held on stack area. The last command of LB1() is RET. It takes two bytes from the top of stack and does jump on address constructed from these bytes. So if the end of your LB1() looks like:
LB1: .... PUSH DPL1 PUSH DPS RET
;void INT0 (void) intterupt x using y PUSH DPL PUSH DPH MOV DPTR,#MyFunc CALL SafeRun ; <- common for all the interrupts POP DPH POP DPL RET ; Common function which saves resisters, goes to subroutine with address in DPTR and retrives registers back SafeRun: PUSH PSW PUSH ACC ; .... push rest registers except DPTR (mark1) CALL SafeRun_Go ; .... pop previous pushed registers (mark1) POP ACC POP PSW RET SafeRun_Go: CLR A JMP @A+DPTR
Yes, you are right! The precdeing codes can't work correctly. I am so embarrassing to say such words: "everything is under control". So, it seems only LB2 could be optimize.
Your solution is good. Thank you again.
"keil's documents said it will improve the performance of may [many?] library functions" Actually, the manual says, "Using additional data pointers can improve the performance of the following library functions: memcpy, memmove, memcmp, strcpy, and strcmp." (my ephasis). So that's only five library functions, and no guarantee that it will actually help! You need to examine whether any improvement in these few library functions is actually worthwhile in your application, considering the impact of the extra saves on your interrupt performance - which seems, from your post, to be your major concern?