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.
I'm looking to optimize an ISR written in C and wondered why version 6.21 pushes both DPTR when it doesn't use them both?
My guess is that since the ISR does not know which of the 2 dptr's that it is using, that it is just quicker to save both of them.
"why version 6.21 pushes both DPTR when it doesn't use them both?" Oh yes it does! C51 can use the extra DPTR(s) for the memcpy, memmove, memcmp, strcpy, and strcmp library functions. If you're sure that your ISR really doesn't need to save both DPTRs, then disable the dual-DPTR option for the source file containing the ISR. If you don't want to use the extra DPTR(s) at all, then disable the dual-DPTR option for the whole Project.
Be careful in disabling the dual-DPTR option. Even if your ISR doesn't use the memmove, memcmp, strcpy, and strcmp library functions, you can get into trouble with code like the following:
char xdata x[10]; void Isr(void) interrupt 2 { char i; char xdata *p = x; for( i = 1; i != 10; i++ ) *p++ = 1; }
Yes I've seen that. I don't happen to use any of those functions and it's a shame they don't use the dual DPTR for other items. I'm positive my ISR doesn't use dual DPTRs. I've looked at the generated assembly from my C source and I think it's odd they push a register pair they don't use.
Why would that get me into trouble? The code seems ok when dual DPTR is off, but it is pretty inefficient when dual DPTR is on and they aren't used as show below in the two examples:
;DUAL DPTR OFF 0000 C0E0 PUSH ACC 0002 C083 PUSH DPH 0004 C082 PUSH DPL 0006 C0D0 PUSH PSW 0008 75D000 MOV PSW,#00H 000B C002 PUSH AR2 000D C005 PUSH AR5 000F C006 PUSH AR6 0011 C007 PUSH AR7 0013 7E00 R MOV R6,#HIGH x 0015 7F00 R MOV R7,#LOW x 0017 7D01 MOV R5,#01H 0019 ?C0005: 0019 0F INC R7 001A EF MOV A,R7 001B AA06 MOV R2,AR6 001D 7001 JNZ ?C0022 001F 0E INC R6 0020 ?C0022: 0020 14 DEC A 0021 F582 MOV DPL,A 0023 8A83 MOV DPH,R2 0025 7401 MOV A,#01H 0027 F0 MOVX @DPTR,A 0028 0D INC R5 0029 BD0AED CJNE R5,#0AH,?C0005 002C ?C0008: 002C D007 POP AR7 002E D006 POP AR6 0030 D005 POP AR5 0032 D002 POP AR2 0034 D0D0 POP PSW 0036 D082 POP DPL 0038 D083 POP DPH 003A D0E0 POP ACC 003C 32 RETI ;DUAL DPTR ON 0000 C0E0 PUSH ACC 0002 C083 PUSH DPH 0004 C082 PUSH DPL 0006 C085 PUSH DPH1 0008 C084 PUSH DPL1 000A C086 PUSH DPS 000C 758600 MOV DPS,#00H 000F C0D0 PUSH PSW 0011 75D000 MOV PSW,#00H 0014 C002 PUSH AR2 0016 C005 PUSH AR5 0018 C006 PUSH AR6 001A C007 PUSH AR7 001C 7E00 R MOV R6,#HIGH x 001E 7F00 R MOV R7,#LOW x 0020 7D01 MOV R5,#01H 0022 ?C0005: 0022 0F INC R7 0023 EF MOV A,R7 0024 AA06 MOV R2,AR6 0026 7001 JNZ ?C0022 0028 0E INC R6 0029 ?C0022: 0029 14 DEC A 002A F582 MOV DPL,A 002C 8A83 MOV DPH,R2 002E 7401 MOV A,#01H 0030 F0 MOVX @DPTR,A 0031 0D INC R5 0032 BD0AED CJNE R5,#0AH,?C0005 0035 ?C0008: 0035 D007 POP AR7 0037 D006 POP AR6 0039 D005 POP AR5 003B D002 POP AR2 003D D0D0 POP PSW 003F D086 POP DPS 0041 D084 POP DPL1 0043 D085 POP DPH1 0045 D082 POP DPL 0047 D083 POP DPH 0049 D0E0 POP ACC 004B 32 RETI
What happens if the run task is using the alternate dptr when the ISR is envoked? The ISR does not change the dptr selector. The dptr register is setup using dpl & dph. The dptr register is accessed using dptr, which is now using dpl1 & dph1. RAM would get very corrupted on an intermittent basis. This would be a nasty bug that could slip though testing.
"dual DPTR is on and they aren't used" As quoted earlier, C51 only ever uses the extra DPTR(s) in the specific Library functions; nowhere else.
Actually you are wrong. The ISR DOES change the DPTR selector: 000A C086 PUSH DPS 000C 758600 MOV DPS,#00H It's forced to use DPTR0 as shown above, which means there is no need to push and pop DPTR1.
No, look at your own posting. There is no "MOV DPS,#00H" in the single DPTR case.
I repeat, that the absence of the memmove, memcmp, strcpy, and strcmp library functions in a ISR, is NOT suffcient for turning off the "dual DPTR option" only in the ISR. If you do, you can generate a very nasty bug. Of course this program failure can only occur if another task call these library rountines, or if you play around with the dptr selector yourself. (If you are not doing this, then why are you even using the "dual DPTR option"?) Think twice before you turn off this option only in an ISR.
Yes I know. I meant in the "use dual dptr" case. Now I see you were talking about the other case. Ok, so you're right about that, and I'm right that there is no reason to push the other dptr in the "use dual" case because it isn't used in the ISR. :)
I aggree that pushing the the 2nd dptr is unneccessary, if you do not use the 2nd dptr. Just as a general comment, Dual DPTR's are very over rated. Unless you move large blocks of data around, I would stick with the single DPTR option.
Well I'm planning on using it, but it seems I'm going to have to use it by dealing with inline assembler. I'm surprized Keil doesn't try to use it more often. In fact, I'm looking at the ASM listing for memcpy and I see something that is mildly disturbing. To switch back and forth between the DPTRs, they are incrementing the DPS (at addr 0x86) repeatedly. In the current revision of silicon, only the LSB is used, but what happens down the road if some of those other bits are used. All this code will just blow up??
I have a good contact at Cypress and he was one of the people that developed the EZUSB 8051 based devices. He told me (for the record): "I believe it's safe, since the "INC DPS" technique is recommended in the Dallas literature (Dallas invented the 4-clock cycle 8051 and added the second data pointer). The Synopsys 8051 core we used in EZ-USB is based on the Dallas architecture." So I guess my fears are put to rest!
I think some variants do have more than 2 DPTRs