SparkFun Forums 

Where electronics enthusiasts find answers.

Everything ARM and LPC
By odriew
#159535
Hello all,
I'm attempting to control the Wiznet W5100 module using the LPC2138 SSP controller. I've read up on SSP usage and the Wiznet SPI command structure, and the following code SHOULD set p to 0x0F (for further testing). However, every read on SSPDR returns 0x00. I've posted code and a schematic to help determine why SSPDR reads 0x00, whether it be improper SSP usage or trouble with the Wiznet module (I suspect the latter).

Schematic: https://dl.dropboxusercontent.com/u/131 ... ematic.png
Code: Select all
//SPI1/SSP initialization ~~~~~~~~~~~~~~~~~~~~~~~~
	//initialize p0.20(SSEL) as GPIO output, idle high
 	IO0DIR |= 0x00100000;
	IO0SET = 0x00100000;

	//connect p0.17-19 to SSP controller, p0.20 to GPIO
	PINSEL1= ((PINSEL1 & ~0x000003FC) | 0x000000A8);
	
	//8-bit SPI w/ PCLK / 2
	SSPCPSR= 0x00000002;
	SSPCR0= 0x00000007;
	
	//enable SPI
	SSPCR1= 0x00000002;
//end SPI1/SSP initialization ~~~~~~~~~~~~~~~~~~~~

	IO0DIR |= LEDPIN;	
	
	IO0CLR= 0x00100000;
	SSPDR= 0xF0;
	SSPDR= 0x00;
	SSPDR= 0x00;
	SSPDR= 0x01;
	while(SSPSR & BSY);	
	IO0SET= 0x00100000; 
	for(i= 0; i < 4; i++) q[i]= SSPDR;
	
	p=   (q[0] == 0x00) ? 8 : 0;
	p += (q[1] == 0x01) ? 4 : 0;
	p += (q[2] == 0x02) ? 2 : 0;
	p += (q[3] == 0x03) ? 1 : 0;
By stevech
#159689
I don't have free time to pore over the code. E.g., one normally codes bit numbers for readability, such as
IO0DIR |= (1<<ABITNUMBER);
And one normally uses named constants and bits rather than what we see in PINSEL1 and all the rest. The bit definitions and so on are in standard LPC2xxx chip .h files.

But I can say that my LPC2016 code using the SPI interface (not sure why you call it SSP- just jargon I guess), does work fine.
Did you consider starting with example working code?
If not, you'll need a 'scope confirm that the port is transmitting correctly.
By UhClem
#159690
stevech wrote:But I can say that my LPC2016 code using the SPI interface (not sure why you call it SSP- just jargon I guess), does work fine.
The LPC2138 has two different SPI ports. The second is called SPI1/SSP (Synchronous Serial Port) and is faster with higher clock speeds and 8 level FIFOs for data.


One obvious thing missing from the initialization code is enabling power to the SSP port. Unless that is done somewhere else, you need to set the appropriate bit in register PCONP. As the manual says:
Important: valid read from a peripheral register and valid write to a peripheral
register is possible only if that peripheral is enabled in the PCONP register!
By odriew
#159692
PCOMP is initialized with all peripherals enabled, is it not? Is there some special power initialization procedure involved even though SPI1 is enabled by default?
By UhClem
#159701
odriew wrote:PCOMP is initialized with all peripherals enabled, is it not? Is there some special power initialization procedure involved even though SPI1 is enabled by default?
Are you certain that the C startup code provided by the library doesn't turn anything off?

It appears that you have the SSP clock set to PCLK/2. Is PCLK less than 30MHz?

Have you tried the loopback mode?
By odriew
#159703
PCLK is the same as the processor clock, which runs on a 20MHz crystal oscillator, so it is less than 30MHz. How does that affect SPI operation?

Loopback mode does work, which is why I might suspect an error in the schematic. I rely on Keil uVision4 to provide startup code (in assembly), but nowhere does it alter any power control registers, as is reflected in the success of loopback mode.
By UhClem
#159704
odriew wrote:PCLK is the same as the processor clock, which runs on a 20MHz crystal oscillator, so it is less than 30MHz. How does that affect SPI operation?
The W5100 data sheet indicates that the SPI clock can have a period no less than 70ns. If PCLK is 20MHz then you should have an SPI clock of 10Mhz which is good. If the LPC2138 PLL is enabled then it might not be.
By odriew
#159706
While I intend to eventually operate via the PLL at 60MHz, 60/5MHz = 12MHz should still be within the theoretical 1/(70ns) = 14.3MHz.

As for the attempts to read from the W5100, I'm expecting a WRITE command to return 0x00, 0x01, 0x02, 0x03. That's not what I get. Does success with loopback mode guarantee that the SPI is working correctly? Any idea as to why I'm only able to read 0x00?
By UhClem
#159707
odriew wrote:As for the attempts to read from the W5100, I'm expecting a WRITE command to return 0x00, 0x01, 0x02, 0x03. That's not what I get. Does success with loopback mode guarantee that the SPI is working correctly? Any idea as to why I'm only able to read 0x00?
Loopback just shows that the internal SPI hardware is working. You could still have a pin configuration or connection problem.(Double check those.) Try an external loopback (connect MISO to MOSI) and see if you read the data you are sending.

You could also try adding an external pullup of 10K or more to the MISO pin. If the data you read changes to 0xff then you know that the W5100 is not responding.

One other thing that puzzles me is that I can't find any indication in the data sheets that the W5100 will generate a power on reset. Perhaps you need to toggle the reset pin instead of just using a pullup.
By stevech
#159732
yes, W5100 needs to be tied to reset. There is a software reset, but I prefer hardware reset.
Also, don't ground chip select on the W5100, use a pull-up. CS is used only for the parallel interface mode. That was a gotcha.
By odriew
#159793
SPI definitely seems to be working. I gave the W5100 a hardware reset (via a piece of wire), and I'm now able to send one WRITE command to it. Exactly one. After getting a response of 0x00, 0x01, 0x02, 0x03, MISO goes high. Interestingly, I can send another single command after resetting the LPC2138, without resetting the W5100.

Also, I left all the bus lines floating. I don't think this is a problem, though, since any shot noise at the floating pin would not cause such a regular and distinct difference between two commands. Perhaps /CS is internally pulled high?
By UhClem
#159800
odriew wrote:SPI definitely seems to be working. I gave the W5100 a hardware reset (via a piece of wire), and I'm now able to send one WRITE command to it. Exactly one. After getting a response of 0x00, 0x01, 0x02, 0x03, MISO goes high. Interestingly, I can send another single command after resetting the LPC2138, without resetting the W5100.
Well, the data you are sending in your sample code does set the indirect bus interface mode bit. The data sheet doesn't say what happens if you do that and then use SPI. But at a guess, I would avoid it. Perhaps setting the msb of the mode register instead (software reset) and poll until it resets would be a better way to start out.
By odriew
#159801
Right, I confused 0x0000 for the port mode register. As of the previous post, however, I did what you said and the first of a series of commands sets the S/W reset bit. However, as mentioned, this first command (or any of the others I've tried) is the only one that seems to respond correctly. In fact, even when I have all of the series of commands set 0x01 (I.B. mode) to MR, only the first responds correctly.

EDIT: I simply misconfigured PINSEL when I switched from software to hardware slave select. IT WORKS.
Last edited by odriew on Thu May 23, 2013 7:13 pm, edited 1 time in total.
By odriew
#159802
UhClem wrote:
odriew wrote:SPI definitely seems to be working. I gave the W5100 a hardware reset (via a piece of wire), and I'm now able to send one WRITE command to it. Exactly one. After getting a response of 0x00, 0x01, 0x02, 0x03, MISO goes high. Interestingly, I can send another single command after resetting the LPC2138, without resetting the W5100.
Well, the data you are sending in your sample code does set the indirect bus interface mode bit. The data sheet doesn't say what happens if you do that and then use SPI. But at a guess, I would avoid it. Perhaps setting the msb of the mode register instead (software reset) and poll until it resets would be a better way to start out.
By the way, congrats on your 100πth post.