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 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 } }
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)
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
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.