EmbeddedRelated.com
Forums
Memfault Beyond the Launch

AT91SAM9 SPI slave mode sample code?

Started by Dan Lyke March 22, 2009
I'm trying to use the AT91SAM9XE in SPI slave mode. Looking through the
source to the Atmel supplied SPI code for the AT91SAM7S256 I'm having
trouble figuring out how to convert some of the functions.

Anyone got a suggestion for SAM9 SPI slave mode sample code?

Thanks.

Dan
On Sun, 22 Mar 2009 17:12:53 -0700
Dan Lyke wrote:
> I'm trying to use the AT91SAM9XE in SPI slave mode. Looking through
> the source to the Atmel supplied SPI code for the AT91SAM7S256 I'm
> having trouble figuring out how to convert some of the functions.

Since posting here invariably means I find the solution to my
problems elsewhere, I figured I'd try another time. If I initialize my
SPI with:

SPI_Configure(AT91C_BASE_SPI1,
AT91C_ID_SPI1,
0);
SPI_ConfigureNPCS(AT91C_BASE_SPI1, 0,
AT91C_SPI_CPOL |
AT91C_SPI_BITS_8 );
SPI_Enable(AT91C_BASE_SPI1);

I can then do
for (int i = 0; i < sizeof(buf); ++i)
buf[i] = SPI_Read(AT91C_BASE_SPI1);

And it works fine. However, if I try to replace that with:

SPI_ReadBuffer(AT91C_BASE_SPI1, buf, sizeof(buf));
while (!SPI_IsFinished(0)) {}

I get an immediate return.

Suggestions or comments appreciated, I think the next step is to break
out both SPI_ReadBuffer and SPI_IsFinished inline into my code and try
to figure out the details of why they're failing.

Dan
On Mon, 30 Mar 2009 10:59:20 -0700
Dan Lyke wrote:
> SPI_ReadBuffer(AT91C_BASE_SPI1, buf, sizeof(buf));
> while (!SPI_IsFinished(0)) {}

Answering myself again: SPI_IsFinished only applies to writing. For
reading you have to do buffer management manually, for example, to
read into the primary buffer:

spi->SPI_RPR = buffer;
spi->SPI_RCR = length;
spi->SPI_PTCR = AT91C_PDC_RXTEN;
while (spi->SPI_RCR) {}

Unfortunately, the at91lib/peripherals/spi/spi.* files are merely
suggestions and templates, understanding how they're using the
registers is the right way to go.

Dan

Thanks for keeping us posted on this Dan.
Appreciate that - I'm sure I'll be faced with SPI sooner than later in my
Linux ventures, might help...
I was going to ask *how* the for(;;) loop was different wrt it working
properly, as opposed to the
single line.
Being in Slave mode, did you want to convey that the line *should* have
been waiting until the SPI receives a char clocked in ?
I wasn't really sure what you
(i) expected as normal behaviour
(ii) how it was actually behaving (not stopping on the offending line I
presume ?)

PS : Is SPI_IsFinished() an IAR intrinsic or lib function, or some such ?

Best Regards,
kris
On Tue, 31 Mar 2009 09:22:36 -0700, Dan Lyke wrote:
> On Mon, 30 Mar 2009 10:59:20 -0700
> Dan Lyke wrote:
>> SPI_ReadBuffer(AT91C_BASE_SPI1, buf, sizeof(buf));
>> while (!SPI_IsFinished(0)) {}
>
> Answering myself again: SPI_IsFinished only applies to writing. For
> reading you have to do buffer management manually, for example, to
> read into the primary buffer:
>
> spi->SPI_RPR = buffer;
> spi->SPI_RCR = length;
> spi->SPI_PTCR = AT91C_PDC_RXTEN;
> while (spi->SPI_RCR) {}
>
> Unfortunately, the at91lib/peripherals/spi/spi.* files are merely
> suggestions and templates, understanding how they're using the
> registers is the right way to go.
>
> Dan
>
>
On Wed, 01 Apr 2009 05:30:41 +1100
m...@virginbroadband.com.au wrote:
> Being in Slave mode, did you want to convey that the line *should*
> have been waiting until the SPI receives a char clocked in ?

Yeah, I was looking for the way to block until the read finished.

> PS : Is SPI_IsFinished() an IAR intrinsic or lib function, or some
> such ?

The various SPI_Configure*/SPI_Read*/etc functions are the ones from
the at91lib/peripherals/spi/ subdirectories provided in the Atmel
"softpack" ZIP files. That's where I generally turn first for guidance,
at least when I'm coding directly to the hardware. Start with that
source code, and then use the names I find there to search in the
datasheet.

I use the GNU compiler, but I assume they're included in the IAR .ZIP
files as well.

Dan
Good-o.
Perhaps a tip wrt the Atmel "GCC" code examples.
The projects that I've ported to CrossWorks (so far) from that softpack aren't that often
proper GCC.
Especially, you'll notice that when alignment is at stake, the IAR version uses #pragma,
but the "fallback" on GCC ignores it - no __atrribute__ whatsoever.
So if things get broken, that's the first place to look if you think alignment might be
crucial !

Best Regards,
Kris

> -----Original Message-----
> From: A... [mailto:A...] On Behalf Of Dan
> Lyke
> Sent: Wednesday, 1 April 2009 6:03 AM
> To: A...
> Subject: Re: [AT91SAM] AT91SAM9 SPI slave mode sample code?
>
> On Wed, 01 Apr 2009 05:30:41 +1100
> m...@virginbroadband.com.au wrote:
> > Being in Slave mode, did you want to convey that the line *should*
> > have been waiting until the SPI receives a char clocked in ?
>
> Yeah, I was looking for the way to block until the read finished.
>
> > PS : Is SPI_IsFinished() an IAR intrinsic or lib function, or some
> > such ?
>
> The various SPI_Configure*/SPI_Read*/etc functions are the ones from
> the at91lib/peripherals/spi/ subdirectories provided in the Atmel
> "softpack" ZIP files. That's where I generally turn first for guidance,
> at least when I'm coding directly to the hardware. Start with that
> source code, and then use the names I find there to search in the
> datasheet.
>
> I use the GNU compiler, but I assume they're included in the IAR .ZIP
> files as well.
>
> Dan


Memfault Beyond the Launch