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.
Hi I want to use the second data pointer available in Dallas, since i am reading my port and then immediatly writing this data to external ram.All this has to be done in ISR in 10us. I am using in line assembly but the code is not working when i use both data pointers. void external0(void) interrupt 0 using 1 { //TRACK1[LEN_TRK1++]=XBYTE[0x8000]; //TRACK1[LEN_TRK1++] = XBYTE[0x8001]; //The above two C statements are replaced by the below mentioned Assembly code #pragma ASM SETB DPS ; DPS=1 ACTIVE DPTR1 MOV DPTR,#08000H MOVX A,@DPTR ; READ INC DPTR CLR DPS ; DPS=0 ACTIVE DPTR0 MOV DPL,LEN_TRK1+01H MOV DPH,LEN_TRK1 MOVX @DPTR,A ; WRITE INC DPTR SETB DPS ; DPS=1 ACTIVE DPTR1 MOVX A,@DPTR ; READ CLR DPS ; DPS=0 ACTIVE DPTR0 MOVX @DPTR,A ; WRITE INC DPTR MOV LEN_TRK1+01H,DPL MOV LEN_TRK1,DPH #pragma ENDASM } Thanx Faisal
Hi The C code written by both jon's is really impressive. There are certain points which are ambiguous on my part which i should clear. 1. The assembly code in my original query is not the one generated for the commented C code instead it is the one i am adding instead of the C code using in line assembly. 2. The orignal C code and its equivalent asm code generated are xdata unsigned char TRACK1[0x2000];//Track1 buffer is located in first 8k locations of ext ram unsigned int LEN_TRK1;//This has to be int as the data received is in excess of 5k void external0(void) interrupt 0 using 1 { STG2_PST_TRK1 = 0; TR0 = 0; if(CNT_EN2_TRK1==1) { TRACK1[LEN_TRK1++] = XBYTE[0x8000]; TRACK1[LEN_TRK1++] = XBYTE[0x8001]; CNTR1_RST_TRK1 = 1; CNTR1_RST_TRK1 = 0; } else { TRACK1[LEN_TRK1++] = XBYTE[0x8002]; TRACK1[LEN_TRK1++] = XBYTE[0x8003]; CNTR2_RST_TRK1 = 1; CNTR2_RST_TRK1 = 0; } 0000 C0E0 PUSH ACC 0002 C083 PUSH DPH 0004 C082 PUSH DPL 0006 C0D0 PUSH PSW 0008 75D008 MOV PSW,#08H ; 000B C292 CLR STG2_PST_TRK1 C28C CLR TR0 ; 000F 30933C JNB CNT_EN2_TRK1,?C0012 ; SOURCE LINE # 194 0012 908000 MOV DPTR,#08000H 0015 E0 MOVX A,@DPTR 0016 FF MOV R7,A 0017 0500 R INC LEN_TRK1+01H 0019 E500 R MOV A,LEN_TRK1+01H 001B AC00 R MOV R4,LEN_TRK1 001D 7002 JNZ ?C0100 001F 0500 R INC LEN_TRK1 0021 ?C0100: 0021 14 DEC A 0022 2400 R ADD A,#LOW TRACK1 0024 F582 MOV DPL,A 0026 7400 R MOV A,#HIGH TRACK1 0028 3C ADDC A,R4 0029 F583 MOV DPH,A 002B EF MOV A,R7 002C F0 MOVX @DPTR,A ; SOURCE LINE # 195 002D 908001 MOV DPTR,#08001H 0030 E0 MOVX A,@DPTR 0031 FF MOV R7,A 0032 0500 R INC LEN_TRK1+01H 0034 E500 R MOV A,LEN_TRK1+01H 0036 AC00 R MOV R4,LEN_TRK1 0038 7002 JNZ ?C0101 003A 0500 R INC LEN_TRK1 003C ?C0101: 003C 14 DEC A 003D 2400 R ADD A,#LOW TRACK1 003F F582 MOV DPL,A 0041 7400 R MOV A,#HIGH TRACK1 0043 3C ADDC A,R4 0044 F583 MOV DPH,A 0046 EF MOV A,R7 0047 F0 MOVX @DPTR,A ; 0048 D290 SETB CNTR1_RST_TRK1 ; 004A C290 CLR CNTR1_RST_TRK1 ; 004C 803A SJMP ?C0013 004E ?C0012: ; ; SOURCE LINE # 201 004E 908002 MOV DPTR,#08002H 0051 E0 MOVX A,@DPTR 0052 FF MOV R7,A 0053 0500 R INC LEN_TRK1+01H 0055 E500 R MOV A,LEN_TRK1+01H 0057 AC00 R MOV R4,LEN_TRK1 0059 7002 JNZ ?C0102 005B 0500 R INC LEN_TRK1 005D ?C0102: 005D 14 DEC A 005E 2400 R ADD A,#LOW TRACK1 0060 F582 MOV DPL,A 0062 7400 R MOV A,#HIGH TRACK1 0064 3C ADDC A,R4 0065 F583 MOV DPH,A 0067 EF MOV A,R7 0068 F0 MOVX @DPTR,A ; SOURCE LINE # 202 0069 908003 MOV DPTR,#08003H 006C E0 MOVX A,@DPTR 006D FF MOV R7,A 006E 0500 R INC LEN_TRK1+01H 0070 E500 R MOV A,LEN_TRK1+01H 0072 AC00 R MOV R4,LEN_TRK1 0074 7002 JNZ ?C0103 0076 0500 R INC LEN_TRK1 0078 ?C0103: 0078 14 DEC A 0079 2400 R ADD A,#LOW TRACK1 007B F582 MOV DPL,A 007D 7400 R MOV A,#HIGH TRACK1 007F 3C ADDC A,R4 0080 F583 MOV DPH,A 0082 EF MOV A,R7 0083 F0 MOVX @DPTR,A ; 0084 D291 SETB CNTR2_RST_TRK1 ; 0086 C291 CLR CNTR2_RST_TRK1 ; 0088 ?C0013: ; 0088 D292 SETB STG2_PST_TRK1 ; 008A 758A00 MOV TL0,#00H ; 008D 758C4C MOV TH0,#04CH ; 0090 D28C SETB TR0 ; 0092 750000 R MOV ovf_count,#00H ; 0095 D0D0 POP PSW 0097 D082 POP DPL 0099 D083 POP DPH 009B D0E0 POP ACC 009D 32 RETI Now as u can see the asm code generated is wasteful. The real prob is with ram read/write ops others have 1 to 1 correspondence. So i need to ge after these ram ops and boost them. Thanx Faisal
Faisal, I'm using C51 V7, so my results will probably be a little different. 1. There are still some undefined variables in your program. I assumed they are unsigned char data. 2. The size of your function is 152 bytes. 3. The size of my function (modified as explained in my previous post) is 105 bytes. A difference of 47 bytes. I'm pretty sure it runs faster, too. Here it is:
36 void external0(void) interrupt 0 using 1 37 { 38 1 STG2_PST_TRK1 = 0; 39 1 TR0 = 0; 40 1 41 1 if(CNT_EN2_TRK1==1) 42 1 { 43 2 *((unsigned int xdata *) &TRACK1[LEN_TRK1]) = *((unsigned int xdata *) (0x8000)); 44 2 CNTR1_RST_TRK1 = 1; 45 2 CNTR1_RST_TRK1 = 0; 46 2 } 47 1 else 48 1 { 49 2 *((unsigned int xdata *) &TRACK1[LEN_TRK1]) = *((unsigned int xdata *) (0x8002)); 50 2 CNTR2_RST_TRK1 = 1; 51 2 CNTR2_RST_TRK1 = 0; 52 2 } 53 1 54 1 LEN_TRK1 += 2; 55 1 }
; FUNCTION external0 (BEGIN) 0000 C0E0 PUSH ACC 0002 C083 PUSH DPH 0004 C082 PUSH DPL 0006 C0D0 PUSH PSW 0008 75D008 MOV PSW,#08H ; SOURCE LINE # 36 ; SOURCE LINE # 38 000B 750000 R MOV STG2_PST_TRK1,#00H ; SOURCE LINE # 39 000E C28C CLR TR0 ; SOURCE LINE # 41 0010 E500 R MOV A,CNT_EN2_TRK1 0012 B40121 CJNE A,#01H,?C0001 ; SOURCE LINE # 42 ; SOURCE LINE # 43 0015 908000 MOV DPTR,#08000H 0018 E0 MOVX A,@DPTR 0019 FE MOV R6,A 001A A3 INC DPTR 001B E0 MOVX A,@DPTR 001C FF MOV R7,A 001D 7400 R MOV A,#LOW TRACK1 001F 2500 R ADD A,LEN_TRK1+01H 0021 F582 MOV DPL,A 0023 7400 R MOV A,#HIGH TRACK1 0025 3500 R ADDC A,LEN_TRK1 0027 F583 MOV DPH,A 0029 EE MOV A,R6 002A F0 MOVX @DPTR,A 002B A3 INC DPTR 002C EF MOV A,R7 002D F0 MOVX @DPTR,A ; SOURCE LINE # 44 002E 750001 R MOV CNTR1_RST_TRK1,#01H ; SOURCE LINE # 45 0031 750000 R MOV CNTR1_RST_TRK1,#00H ; SOURCE LINE # 46 0034 801F SJMP ?C0002 0036 ?C0001: ; SOURCE LINE # 48 ; SOURCE LINE # 49 0036 908002 MOV DPTR,#08002H 0039 E0 MOVX A,@DPTR 003A FE MOV R6,A 003B A3 INC DPTR 003C E0 MOVX A,@DPTR 003D FF MOV R7,A 003E 7400 R MOV A,#LOW TRACK1 0040 2500 R ADD A,LEN_TRK1+01H 0042 F582 MOV DPL,A 0044 7400 R MOV A,#HIGH TRACK1 0046 3500 R ADDC A,LEN_TRK1 0048 F583 MOV DPH,A 004A EE MOV A,R6 004B F0 MOVX @DPTR,A 004C A3 INC DPTR 004D EF MOV A,R7 004E F0 MOVX @DPTR,A ; SOURCE LINE # 50 004F 750001 R MOV CNTR2_RST_TRK1,#01H ; SOURCE LINE # 51 0052 750000 R MOV CNTR2_RST_TRK1,#00H ; SOURCE LINE # 52 0055 ?C0002: ; SOURCE LINE # 54 0055 7402 MOV A,#02H 0057 2500 R ADD A,LEN_TRK1+01H 0059 F500 R MOV LEN_TRK1+01H,A 005B E4 CLR A 005C 3500 R ADDC A,LEN_TRK1 005E F500 R MOV LEN_TRK1,A ; SOURCE LINE # 55 0060 D0D0 POP PSW 0062 D082 POP DPL 0064 D083 POP DPH 0066 D0E0 POP ACC 0068 32 RETI ; FUNCTION external0 (END)
I think this discussion has lost the woods for the cause of the tree. When copying a byte or two, very little time spent either way and it is easy to make the two approaches (almost) equally fast. If you are copying, say, 112 bytes from one place to another (I do, as part of a string reformatting routine) it is definitely faster to use 2 data pointers, than the code from the compiler.
loop: movx a,@dptr inc dptr ; do something to the accumulator inc auxr movx @dptr,a inc dptr inc auxr djnz r7,loop
A long time ago, I profiled the execution performance of the dual data pointers on the Dallas 320. I think that the break-even is somewhere around 5-6 bytes. That's why I tried to point out that using dual data pointers for only 2 bytes is overly complex and doesn't gain anything. For larger buffers, I agree that dual data pointers speed things up. Jon
"I think this discussion has lost the woods for the cause of the tree." Well yes Erik, but lets be more positive Jon & Jon took the discussion off on a second and interesting line by 'raising to the challenge'. I wouldn't disagree with JW that the break-even point is around 5 or 6 bytes. Efficient and complete C code for an application that can benefit from dual dptrs is another point. We don't necessarily have to answer every point the original question could rise; not that I wish to stop anybody raising to that challenge. In my mind there is also still the question - Will the compiler handle the problem of saving the context (i.e. pushing both dptrs) in an ISR. I suspect not but don't have time to investigate at the moment.
To see the worst case "context saving", just put in an external fn call. If you set the "use dual dptr" option, you get:
extern void fn(void); void external0(void) interrupt 0 using 1 { fn(); } ; FUNCTION external0 (BEGIN) 0000 C0E0 PUSH ACC 0002 C0F0 PUSH B 0004 C083 PUSH DPH 0006 C082 PUSH DPL 0008 C085 PUSH DPH1 000A C084 PUSH DPL1 000C C086 PUSH DPS 000E 758600 MOV DPS,#00H 0011 C0D0 PUSH PSW 0013 75D008 MOV PSW,#08H ; SOURCE LINE # 11 ; SOURCE LINE # 13 0016 120000 E LCALL fn ; SOURCE LINE # 14 0019 D0D0 POP PSW 001B D086 POP DPS 001D D084 POP DPL1 001F D085 POP DPH1 0021 D082 POP DPL 0023 D083 POP DPH 0025 D0F0 POP B 0027 D0E0 POP ACC 0029 32 RETI ; FUNCTION external0 (END)
Yep. With only 2 data pointers, you can get into a lot of crazy situations saving and restoring both data pointers. The infineon 515 has 8 data pointers so you have 2 that are available for each register bank. That kinda makes things better. However, the best utilization of dual data pointers is for moving memory like you would do with memmove, memcpy, and so on. Jon