This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

using 2nd DPTR in DS87C520

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

Parents
  • 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

Reply
  • 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

Children
  • 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      }
    

    and the generated code:

                 ; 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)
    

    Now, if I enable common block subroutines (optimizer level 9) the code size shrinks to 90 bytes and only runs slower by 4 cycles.

    I also considered setting the data pointers at the top of the interrupt and simply incrementing the 8000h by 2 in the else case, but that executes that much more slowly even though the code is smaller by about 13 bytes.

    Maybe someone can take my first cut here and optimize it further.

    Jon

    P.S. One of the things you must remember is that the C compiler is just a tool that makes assembly code out of your C code. The compiler will compile a poorly constructed algorithm as well as a finely tuned one. I can use the finest compiler in the world to compile a bubble sort and a heap sort and still the performance of the bubble sort will be lacking. Check out some of the material from Jon Bently if you REALLY want to learn how to write optimal C code. His books are sufficiently advanced that supreme knowledge of C is required.

  • 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
    

    have fun,

    Erik

  • 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