EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

LPC2368 as SPI slave

Started by "d.holzwarth" September 19, 2007
hi everyone

I have a LPC2368 conntected to a DSP over the SPI. The DSP is set to
master and the LPC should be as slave.
Because a slave can only send/receive data when the master is sending
the DSP "polls" the LPC by transmitting some "poll-string" every 10ms.

My problem now is that i don't know how the slave (LPC) can detect
that the master is transmitting data (and thus start transmitting
data too).

I was thinking if maybe the SSEL signal should/can be used for that
purpose as the master sets the SSEL signal to low when a transfer
starts. However as far as I know you can't check the SSEL signal by
interrupt so you propably would need to poll it which I don't really
want to do...

so if maybe anyone could explain me whats the "best" way for a SPI
slave to detect when it needs to transmit/receive data?

thanks in advance
D. Holzwarth

An Engineer's Guide to the LPC2100 Series

Hi,

you can use the SPI interrupt to see when the LPC shall send.

A normal SPI session looks like this:

* Master asserts chip-select to the slave.
* Master starts clocking the SPI.
* Slave and master samples its input and shifts out its tx data
content to the SPI. Note: data flows from master to slave and
slave to master in parallel.
* When transfer ended master deasserts chip-select.

So, enable the SPI interrupt and it will fire if the SPI is active for
your device. You may create commad/answer phases if you need. (Master
sends a command, slave decodes and gives answer.)

Foltos

d.holzwarth wrote:
> hi everyone
>
> I have a LPC2368 conntected to a DSP over the SPI. The DSP is set to
> master and the LPC should be as slave.
> Because a slave can only send/receive data when the master is sending
> the DSP "polls" the LPC by transmitting some "poll-string" every 10ms.
>
> My problem now is that i don't know how the slave (LPC) can detect
> that the master is transmitting data (and thus start transmitting
> data too).
>
> I was thinking if maybe the SSEL signal should/can be used for that
> purpose as the master sets the SSEL signal to low when a transfer
> starts. However as far as I know you can't check the SSEL signal by
> interrupt so you propably would need to poll it which I don't really
> want to do...
>
> so if maybe anyone could explain me whats the "best" way for a SPI
> slave to detect when it needs to transmit/receive data?
>
> thanks in advance
> D. Holzwarth
>
>
> Yahoo! Groups Links
>
--- In l..., "d.holzwarth" wrote:
>
> hi everyone
>
> I have a LPC2368 conntected to a DSP over the SPI. The DSP is set to
> master and the LPC should be as slave.
> Because a slave can only send/receive data when the master is sending
> the DSP "polls" the LPC by transmitting some "poll-string" every 10ms.
>
> My problem now is that i don't know how the slave (LPC) can detect
> that the master is transmitting data (and thus start transmitting
> data too).
>
> I was thinking if maybe the SSEL signal should/can be used for that
> purpose as the master sets the SSEL signal to low when a transfer
> starts. However as far as I know you can't check the SSEL signal by
> interrupt so you propably would need to poll it which I don't really
> want to do...
>
> so if maybe anyone could explain me whats the "best" way for a SPI
> slave to detect when it needs to transmit/receive data?
>
> thanks in advance
> D. Holzwarth
>

I have been thinking about this very problem. In the case of the PS/2
game controller, the master sends a byte of 0x01 and ignores the
return byte. This is a command to the controller to send data.

The master then sends a byte of 0x42 and receives a reply of 0x41
(digital mode) or 0x73 (analog mode).

The controller then sends 8 (analog mode) or 4 (digital mode) bytes of
0xff and reads the results off the analog joysticks and buttons.

So, you can just load the slave output register with something and it
will shift out when the master shifts a byte in. You will then get an
interrupt and you know it is time to start sending real data.

Or, you can preload the shift register with the first byte of real
data and just do something else until you get an interrupt. To that
end, you might as well just keep the shift register filled from a
circular buffer.

In the end, it depends on which device is the master. A small IO
processor can be a master that sends data to the host controller
whenever it is available. The host may well be the larger controller
but this eliminates polling. When the IO controller has something to
say, it just yells it out.

Richard
> So, enable the SPI interrupt and it will fire if the SPI is active for
> your device

I'm sorry but that sounds a bit odd to me (not that i don't believe you
but rather just don't undertand it :-( ).

As far as I understand the user manual the SPI interrupt fires when the
SPIF bit is set to '1' (or some error bits set to '1').

and the description for the SPIF bit says:
"when a slave, this bit is set on the last data sampling edge of SCK.
this bit is cleared by reading this register (status reg), then
accessing the SPI data register."

so I think my problem of understanding is what is meant by "last
sampling edge of the SCK"?

also the user manual states the following "TODO" for slave operation:

1. set the SPI control register to the desired settings. (thats no
problem :-))
2. write data to be transmitted to the SPI data register (optional).
Note that this can only be done when a slave SPI transfer is not
progress. (how can i detect that no slave transfer is in progess?)
3. wait for the SPIF bit in the SPI status register to be set to 1. The
SPIF bit wil be set after the last sampling clock edge of the SPI data
transfer. (so what does that mean? SPIF is set when data transfer is
over or what?)
4. Read the SPI status register. (no problem :-))
5. read the receive data from SPI data register. (optional)
6. go to step 2 if more data is required to transmit.

sorry for asking such many (probably newbish) questions, but i don't
really understand the above steps (especially step 2 and 3).

would be nice if someone could again help :-)

greets
D. Holzwarth
--- In l..., "d.holzwarth" wrote:
>
> > So, enable the SPI interrupt and it will fire if the SPI is active for
> > your device
>
> I'm sorry but that sounds a bit odd to me (not that i don't believe you
> but rather just don't undertand it :-( ).
>
> As far as I understand the user manual the SPI interrupt fires when the
> SPIF bit is set to '1' (or some error bits set to '1').
>
> and the description for the SPIF bit says:
> "when a slave, this bit is set on the last data sampling edge of SCK.
> this bit is cleared by reading this register (status reg), then
> accessing the SPI data register."
>
> so I think my problem of understanding is what is meant by "last
> sampling edge of the SCK"?
It would be either the rising or falling edge of the clock as shown in
figure 40 of the User Manual. You get to choose whether it is rising
or falling but you have to make both ends agree.
>
> also the user manual states the following "TODO" for slave operation:
>
> 1. set the SPI control register to the desired settings. (thats no
> problem :-))
> 2. write data to be transmitted to the SPI data register (optional).
> Note that this can only be done when a slave SPI transfer is not
> progress. (how can i detect that no slave transfer is in progess?)
Which is why the first byte transferred from the slave to the master
could be defined to be junk. Just like the PS/2 controller.

See below about WCOL.
> 3. wait for the SPIF bit in the SPI status register to be set to 1. The
> SPIF bit wil be set after the last sampling clock edge of the SPI data
> transfer. (so what does that mean? SPIF is set when data transfer is
> over or what?)
Exactly. At the clock edge you defined of the last data bit, the
transfer is complete and SPIF is set.

And, the wait can be a LONG time if the master doesn't want the data.
Sitting in a loop is probably not the way to go.
> 4. Read the SPI status register. (no problem :-))
> 5. read the receive data from SPI data register. (optional)
> 6. go to step 2 if more data is required to transmit.
This is where you KNOW there is no slave transfer in progress because
it just finished so go ahead and stick a databyte in the register.
Set your protocol so that the master must toggle SSEL between bytes
and make sure the master is slow enough or waits long enough for this
controller to get the byte to the register.

If you make a mistake in step 2, you will get a WCOL interrupt. So,
attempting to write while a transfer is in progress is not really an
issue. Or, at least, it can be handled.

If your message frames are of a known length, after you transfer the
last byte of the frame, go ahead and stick a junk char in the shift
register to be used at step 2 when the next transfer begins.

The idea of having a junk char in the transaction is not really
necessary as long as the slave device knows exactly what data to send
to the master as the first byte of a frame. For the PS/2, the command
byte from the master is the first clue the controller has as to the
data required. Therefore, it is impossible to have the data sitting
in the output register. Thus the junk byte send in reply to the
command byte from the master.

It's usually a lot easier to make SPI work than I2C. Still, a logic
analyzer can be helpful.

Richard
Hi,

please see my comments below.

d.holzwarth wrote:
>> So, enable the SPI interrupt and it will fire if the SPI is active for
>> your device
>>
>
> I'm sorry but that sounds a bit odd to me (not that i don't believe you
> but rather just don't undertand it :-( ).
>
> As far as I understand the user manual the SPI interrupt fires when the
> SPIF bit is set to '1' (or some error bits set to '1').
>
> and the description for the SPIF bit says:
> "when a slave, this bit is set on the last data sampling edge of SCK.
> this bit is cleared by reading this register (status reg), then
> accessing the SPI data register."
>
> so I think my problem of understanding is what is meant by "last
> sampling edge of the SCK"?
>
>
The SPI has four wires.

* CS alias chip select. Usually this is active low and and selects
which slave may use the SPI bus. Each slave has its own CS line.
* MOSI: master out serial in. This is a data line output for the
master and input for the slaves.
* MISO: master in serial out.
* CLK: clock. On this line the master transits its SPI clock signal
to synchronize the transfer.

Let's see how it is working. The master selects the slave it wants to
talk to using the proper CS line. Then starts outputting clock signal on
the CLK line and starts driving MOSI and sampling MISO. If the CS is
active for the slave (and currently it is) it will sample the MOSI
signal and drive the MISO. Depending on the configuration of the SPI
(slave and master config must match) one device will sample on the
rising edge and make its output stable on the falling edge, and the
other device will do the opposite, sample in the falling edge and make
its output stable on the rising.

Thus SPIF bit will be set at the end of each character. Character length
can be configured too (usually 8 or 16 bit). Note: if one device is not
sending, the other is still sampling its input line and thus will
receive either all ones (e.g. 0xff) or all zeros (0x0).

> also the user manual states the following "TODO" for slave operation:
>
> 1. set the SPI control register to the desired settings. (thats no
> problem :-))
> 2. write data to be transmitted to the SPI data register (optional).
> Note that this can only be done when a slave SPI transfer is not
> progress. (how can i detect that no slave transfer is in progess?)
>
You don't need to detect. After you write the TX register always wait
for SPIF set. SPIF means TX register is empty.
> 3. wait for the SPIF bit in the SPI status register to be set to 1. The
> SPIF bit wil be set after the last sampling clock edge of the SPI data
> transfer. (so what does that mean? SPIF is set when data transfer is
> over or what?)
>
SPI is always double direction. All nodes connected to it are receiving
and transmitting in parallel. If you don't fill the TX buffer, then the
output line remains idle and the other end will receive 0x0 or 0xff. The
node on the other end in this case can not know if the received data is
sent by the other side or the line is just idle. In SPI communication
the both nodes must follow a strict protocol telling which node is
talking to a line and when.

> 4. Read the SPI status register. (no problem :-))
> 5. read the receive data from SPI data register. (optional)
> 6. go to step 2 if more data is required to transmit.
>
> sorry for asking such many (probably newbish) questions, but i don't
> really understand the above steps (especially step 2 and 3).
>
No problem. Maybe others emails will be more clear.
> would be nice if someone could again help :-)
>
> greets
> D. Holzwarth
>
> Yahoo! Groups Links
>
thanks everyone for the clarifications :-)

I'll go through my code of the SPI slave tomorrow and double check it
with all your suggestions (and maybe post in here again ;-)).

but I think I understand it correct that the SPI slave is just "one
byte behind" the Master. so at the start of the transfer there's a junk
buyte (in my case 0x00) in the slave transmit buffer (thats what I did)
and as soon as the slave gets an SPI interrupt it can read the SPI data
register (for received master data) and then put its own meaningful
data into that register (in that case there shoulndt occur any WCOL
errors, right?).

I think thats how I did in my code.

one thing I'm a bit unsure bout tho is what foglaltid mentioned about
the data line being idle when you send all zeroes. cause thats what my
slave does when there's no meaningfull data to send. In a system where
you have only 1 slave and 1 master that shouldn't be a problem, right?
Hi,

it is true the first character is junk, but you don't need to specify
it's value by writing something to the TX buffer. Idle bus state is good
enough. On the other hand sending something can not harm. The only
important this is the master must know the first byte is junk.

Foltos

d.holzwarth wrote:
> thanks everyone for the clarifications :-)
>
> I'll go through my code of the SPI slave tomorrow and double check it
> with all your suggestions (and maybe post in here again ;-)).
>
> but I think I understand it correct that the SPI slave is just "one
> byte behind" the Master. so at the start of the transfer there's a junk
> buyte (in my case 0x00) in the slave transmit buffer (thats what I did)
> and as soon as the slave gets an SPI interrupt it can read the SPI data
> register (for received master data) and then put its own meaningful
> data into that register (in that case there shoulndt occur any WCOL
> errors, right?).
>
> I think thats how I did in my code.
>
> one thing I'm a bit unsure bout tho is what foglaltid mentioned about
> the data line being idle when you send all zeroes. cause thats what my
> slave does when there's no meaningfull data to send. In a system where
> you have only 1 slave and 1 master that shouldn't be a problem, right?
>
>
> Yahoo! Groups Links
>

The 2024 Embedded Online Conference