Skip to content

Speeding up the Bagels Server

July 18, 2014

Most of the server’s time is spent transferring data to and from the wiznet card. The protocol is a big part of the issue. For each byte to be sent you have to transfer four bytes over SPI: the first byte is the write opcode, the next two are the address in the wiznet bufer(which advances for each write) and the last one is the byte to be written. In addition, the chip wants you to lower it’s slave select and raise it for each byte.

Here’s the wizWriteN routine that transfers the data.

void wiz_WriteN(unsigned int offaddr,unsigned char *data, unsigned int N)
{
  //printf("\nwiz_WriteN(%x,%s,%d) ",offaddr,data,N);
  SPINpayload.opcode=WIZNET_WRITE_OPCODE; //prep for sequence of writes
  while(N>0){//for all the bytes to be transferred
  	SPINpayload.realaddr=TXBUFADDR+(offaddr&TX_BUF_MASK);
  	SPINpayload.data=*data;
  	//p4hex(&SPINpayload.opcode);
  	enablewiz();   			// Activate the CS pin
  	spiSendN(&SPINpayload.opcode,4);
  	disablewiz();				// make CS pin not active
  	offaddr++;data++;N--;
  }
}

Her’s the while loop compiled to 1802 assembly

;  while(N>0){//for all the bytes to be transferred
;  	SPINpayload.realaddr=TXBUFADDR+(offaddr&TX_BUF_MASK);
	alu2I R11,R7,2047,ani,ani ;removed copy;BANDU2(reg,con)
	ldA2 R11,'O',R11,(16384); reg:addr
	st2 R11,'D',(_SPINpayload+1),0; ASGNU2(addr,reg)
;  	SPINpayload.data=*data;
	ldaD R11,_SPINpayload+3; reg:acon
	ldn1 R10,R6;reg:  INDIRU1(indaddr)
	str1 R10,R11; ASGNU1(indaddr,reg)		DH
;  	enablewiz();   			// Activate the CS pin
	ldad memaddr,_PIN4
	ldn memaddr
	ani 0x7f
	str memaddr
	sex memaddr
	out 4
	sex 2
;  	spiSendN(&SPINpayload.opcode,4);
	ldaD R12,_SPINpayload; reg:acon
	ldaD R13,4; reg:acon
	Ccall _spiSendN
;  	disablewiz();				// make CS pin not active
	ldad memaddr,_PIN4
	ldn memaddr
	ori 0x80
	str memaddr
	sex memaddr
	out 4
	sex 2
;  	offaddr++;data++;N--;
	incm R7,1
	incm R6,1
	decm R1,1
;  }

and here’s the spiSendN routine which is already an assembly routine

_spiSendN:
	sex 12
$$spiSendLoop:
	out 6
	dec 13
	glo 13
	bnz $$spiSendLoop
	ghi 13
	bnz $$spiSendLoop
	sex 2
	cretn
	align 16
_spiReceiveN:
	sex 12
	dec 12
$$spiRxvLoop:
	out 6
	dec 13
	inp 6
	glo 13
	bnz $$spiRxvLoop
	ghi 13
	bnz $$spiRxvLoop
	sex 2
	cretn
;} //that's it

So, I make all that about 25+45 baseline plus 125 instructions per payload byte. For a 200 byte transmission that’s 25,000 instructions or 100ms which corresponds well to what I measure.
I think that could probably come down to 100 baseline plus 25 per payload byte.

Advertisements

From → web server

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: