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

DPTR constantly reloaded

I have some code to transfer a large amount of data over a SPI port running at the system clock/2 so I need my code to be as fast as possible. The code generated for my current method does not seem to be as optimal as it could be. I am using optimization (8, speed) with the 7.07 C51. Here is a simplified version of my code:

//this variable set in buffer data function
static unsigned char xdata * data spiDataPtr;

void transferData(void) small {
     //do not want to store changes in
     //spiDataPtr so use temp pointer
     unsigned char xdata * tempPtr;
     unsigned char data i;
     unsigned char data temp;

     tempPtr = spiDataPtr;

     //transfer set block size
     for(i = 0xff; i != 0; i--) {
          SPIDATA = *tempPtr; //initiate transfer
          tempPtr++; //prepare for next send while busy transfering
          while(!SPITXDONE); //wait for transfer to complete
          temp = SPIDATA; //read to avoid colission error
     }
}

The compiler increments tempPtr in its data location and then reloads it into the DPTR each time tempPtr is increased. I do not need the final value of tempPtr. What I would like is for the DPTR to be loaded when tempPtr is initially set and then for the DPTR to be increased by INC DPTR. I figure this would be quicker even if the value of tempPtr was needed because the DPTR could be moved back into tempPtr at the end of the loop. Is there a way to get the compiler to do this short of assembly?

Parents
  • Here's what I get when I compile with C51 V7.07. Note that I just made up address values for the SPI SFRs.

                 ; FUNCTION transferData (BEGIN)
                                               ; SOURCE LINE # 6
                                               ; SOURCE LINE # 13
    ;---- Variable 'tempPtr' assigned to Register 'DPTR' ----
    0000 850082      R     MOV     DPL,spiDataPtr+01H
    0003 850083      R     MOV     DPH,spiDataPtr
                                               ; SOURCE LINE # 16
    ;---- Variable 'i' assigned to Register 'R7' ----
    0006 7FFF              MOV     R7,#0FFH
    0008         ?C0001:
                                               ; SOURCE LINE # 17
    0008 E0                MOVX    A,@DPTR
    0009 F590              MOV     SPIDATA,A
                                               ; SOURCE LINE # 18
    000B A3                INC     DPTR
    000C         ?C0004:
                                               ; SOURCE LINE # 19
    000C 3091FD            JNB     SPITXDONE,?C0004
    000F         ?C0005:
                                               ; SOURCE LINE # 20
    000F 859000      R     MOV     temp,SPIDATA
                                               ; SOURCE LINE # 21
    0012 DFF4              DJNZ    R7,?C0001
                                               ; SOURCE LINE # 22
    0014         ?C0006:
    0014 22                RET
                 ; FUNCTION transferData (END)
    

    This sounds like what you are looking for. I used optimizer level 8, speed. Maybe there is something else you are doing?

    Jon

Reply
  • Here's what I get when I compile with C51 V7.07. Note that I just made up address values for the SPI SFRs.

                 ; FUNCTION transferData (BEGIN)
                                               ; SOURCE LINE # 6
                                               ; SOURCE LINE # 13
    ;---- Variable 'tempPtr' assigned to Register 'DPTR' ----
    0000 850082      R     MOV     DPL,spiDataPtr+01H
    0003 850083      R     MOV     DPH,spiDataPtr
                                               ; SOURCE LINE # 16
    ;---- Variable 'i' assigned to Register 'R7' ----
    0006 7FFF              MOV     R7,#0FFH
    0008         ?C0001:
                                               ; SOURCE LINE # 17
    0008 E0                MOVX    A,@DPTR
    0009 F590              MOV     SPIDATA,A
                                               ; SOURCE LINE # 18
    000B A3                INC     DPTR
    000C         ?C0004:
                                               ; SOURCE LINE # 19
    000C 3091FD            JNB     SPITXDONE,?C0004
    000F         ?C0005:
                                               ; SOURCE LINE # 20
    000F 859000      R     MOV     temp,SPIDATA
                                               ; SOURCE LINE # 21
    0012 DFF4              DJNZ    R7,?C0001
                                               ; SOURCE LINE # 22
    0014         ?C0006:
    0014 22                RET
                 ; FUNCTION transferData (END)
    

    This sounds like what you are looking for. I used optimizer level 8, speed. Maybe there is something else you are doing?

    Jon

Children
  • Hi,
    I think you should use #ASM/ENDASM for routines which must be as fast as possible really. Even example shown above is not fast enough. Really, it may be optimized much more:

    	MOV     R7,#0FFH
    LOOP:
    	MOVX    A,@DPTR
    	JNB     SPITXDONE,$
    	XCH     A,SPIDATA
    	INC     DPTR
    	DJNZ	R7,LOOP
    	RET
    Here both MOVX and DJNZ are included inside wait state aswell -- hope it shows you that ASM-coding is useful (=
    Btw, what the MCU do you use? The reason I ask is the SPITXDONE bit; I have not seen that bit before anywhere and do not sure that it may be bit-addressable.
    Good days!

  • Ah, thanks for the information Jon. I was indeed doing a little bit more in the function but I did not think it would matter as I was not manipulating any other xdata variables, just resetting and reusing the tempPtr. After moving the extra code out of the function it compiled the way I thought it should have initially.

    The ASM example is interesing Oleg and I will keep it in mind for future projects, but for mantainability reasons I am trying to avoid ASM in this project. I actually have the C code set up to do the DJNZ during the wait state and with the DPTR being incemented properly now the extra code of the C version still takes just below the SPI transfer time. There will only be 2 clocks lost by not having the XCH command and that is acceptable. I am using a Cygnal chip so the commands take very few clock cycles. The SPI tx done flag is indeed bit addressable.