For users of the Atmel AT91SAM7 and AT91SAM9 ARM CPU chips. Atmel has taken a new direction by combining on chip flash and ram with the ARM CPU on a single die. This provides low cost devices for small systems using the ARM CPU.
This group is to exchange information to help users get started and learn how to use the devices.
SPI and TDRE - jruc...@ssccorp.com - Feb 4 13:45:15 2008
I'm doing interrupt I/O on the SPI. Everything seems to work fine for small transfers (<30
bytes). If I try to transfer 100 bytes, the TDRE stops changing. I don't see any sign of
overflow, but I cannot see why TDRE would stop changing, when there are still bytes to
write? Also RDRF stops changing.
This is on an embedded linux system, here's the latest version of the ISR:
wait_queue_head_t spi_queue;
long spi_status;
static irqreturn_t spi_interrupt(int irq, void *dev_id)
{
spi_status = at91_spi_read(AT91_SPI_SR);
while (
((spi_status & AT91_SPI_RDRF) && (rx_index
((spi_status & AT91_SPI_TDRE) && (tx_index
)
{
// if there is a byte there, read it
if ((spi_status & AT91_SPI_RDRF) && (rx_index
{
rx_buffer[rx_index++] = at91_spi_read(AT91_SPI_RDR);
if (rx_index>=rx_count)
{
// Disable the rcv interrupts from the SPI
at91_spi_write(AT91_SPI_IDR,AT91_SPI_RDRF);
}
}
// we will get more TDRE than we have data to tx, since the rx data
// arrives sometime after the tx, and there is no way to tell which
// generated the interrupt, so check the tx_count
if ((spi_status & AT91_SPI_TDRE) && (tx_index
{
at91_spi_write(AT91_SPI_TDR,tx_buffer[tx_index++]);
if (tx_index>=tx_count)
{
// Disable the tx interrupts from the SPI
at91_spi_write(AT91_SPI_IDR,AT91_SPI_TDRE);
}
}
spi_status = at91_spi_read(AT91_SPI_SR);
}
if (rx_index>=rx_count)
wake_up_interruptible(&spi_queue);
spi_int_count++; // debug
return IRQ_HANDLED;
}

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: SPI and TDRE - Chris DeLise - Feb 4 18:10:37 2008
I wish I knew how the interrupt and status register flags were wired up. In my case
hooking up a scope to NCSx, MISO, and MOSI gave me the needed information. I'm doing
bursts of 4-6 words at a time within a single ISR call, so I spin waiting for TDRE & RDRF.
TDRE goes high nearly immediately after writing a word - probably right after it transfers
into the shift register. RDRF seems to assert about 1.2 uS after NCS deasserts. It should
be immediate, not 60+ MCLK cycle times, and I don't know what causes the delay. Also it
might vary with the baud rate, which is about 80ns per bit (SCBR=4, 48 MHz MCLK).
I'm assuming your At91 is the SPI Master, right? If not all bets are off. I'd try the
scope (a DSO if you've got one) and see if data is actually being sent. Also, is there the
possibility of nested interrupts, something you probably want to avoid. When your TDRE
stops changing, is it stuck high or low?
Chris
----- Original Message -----
From: j...@ssccorp.com
To: A...@yahoogroups.com
Sent: Monday, February 04, 2008 1:28 PM
Subject: [AT91SAM] SPI and TDRE
I'm doing interrupt I/O on the SPI. Everything seems to work fine for small transfers
(<30 bytes). If I try to transfer 100 bytes, the TDRE stops changing. I don't see any sign
of overflow, but I cannot see why TDRE would stop changing, when there are still bytes to
write? Also RDRF stops changing.
This is on an embedded linux system, here's the latest version of the ISR:
wait_queue_head_t spi_queue;
long spi_status;
static irqreturn_t spi_interrupt(int irq, void *dev_id)
{
spi_status = at91_spi_read(AT91_SPI_SR);
while (
((spi_status & AT91_SPI_RDRF) && (rx_index
((spi_status & AT91_SPI_TDRE) && (tx_index
)
{
// if there is a byte there, read it
if ((spi_status & AT91_SPI_RDRF) && (rx_index
{
rx_buffer[rx_index++] = at91_spi_read(AT91_SPI_RDR);
if (rx_index>=rx_count)
{
// Disable the rcv interrupts from the SPI
at91_spi_write(AT91_SPI_IDR,AT91_SPI_RDRF);
}
}
// we will get more TDRE than we have data to tx, since the rx data
// arrives sometime after the tx, and there is no way to tell which
// generated the interrupt, so check the tx_count
if ((spi_status & AT91_SPI_TDRE) && (tx_index
{
at91_spi_write(AT91_SPI_TDR,tx_buffer[tx_index++]);
if (tx_index>=tx_count)
{
// Disable the tx interrupts from the SPI
at91_spi_write(AT91_SPI_IDR,AT91_SPI_TDRE);
}
}
spi_status = at91_spi_read(AT91_SPI_SR);
}
if (rx_index>=rx_count)
wake_up_interruptible(&spi_queue);
spi_int_count++; // debug
return IRQ_HANDLED;
}
------------------------------------------------------------------------------
No virus found in this incoming message.
Checked by AVG Free Edition.
Version: 7.5.516 / Virus Database: 269.19.19/1258 - Release Date: 2/4/2008 10:10 AM

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )
Re: SPI and TDRE - jeff_rucker - Feb 4 19:29:35 2008
Thanks for the comments. This is an AT91 as master application. When
the data gets stuck - either TDRE is low, or RDRF never goes high. I
think it is related to the chip select signals - seems to work better
if I do not use the CSAAT (CS remains high). Still very confusing. I
am going to look at it on a storage scope -
--- In A...@yahoogroups.com, "Chris DeLise"
wrote:
>
> I wish I knew how the interrupt and status register flags were
wired up. In my case hooking up a scope to NCSx, MISO, and MOSI gave
me the needed information. I'm doing bursts of 4-6 words at a time
within a single ISR call, so I spin waiting for TDRE & RDRF. TDRE
goes high nearly immediately after writing a word - probably right
after it transfers into the shift register. RDRF seems to assert
about 1.2 uS after NCS deasserts. It should be immediate, not 60+
MCLK cycle times, and I don't know what causes the delay. Also it
might vary with the baud rate, which is about 80ns per bit (SCBR=4,
48 MHz MCLK).
>
> I'm assuming your At91 is the SPI Master, right? If not all bets
are off. I'd try the scope (a DSO if you've got one) and see if data
is actually being sent. Also, is there the possibility of nested
interrupts, something you probably want to avoid. When your TDRE
stops changing, is it stuck high or low?
>
> Chris
>
> ----- Original Message -----
> From: jrucker@...
> To: A...@yahoogroups.com
> Sent: Monday, February 04, 2008 1:28 PM
> Subject: [AT91SAM] SPI and TDRE
> I'm doing interrupt I/O on the SPI. Everything seems to work fine
for small transfers (<30 bytes). If I try to transfer 100 bytes, the
TDRE stops changing. I don't see any sign of overflow, but I cannot
see why TDRE would stop changing, when there are still bytes to
write? Also RDRF stops changing.
>
> This is on an embedded linux system, here's the latest version of
the ISR:
>
> wait_queue_head_t spi_queue;
> long spi_status;
> static irqreturn_t spi_interrupt(int irq, void *dev_id)
> {
> spi_status = at91_spi_read(AT91_SPI_SR);
>
> while (
> ((spi_status & AT91_SPI_RDRF) && (rx_index
> ((spi_status & AT91_SPI_TDRE) && (tx_index
> )
> {
> // if there is a byte there, read it
> if ((spi_status & AT91_SPI_RDRF) && (rx_index
> {
> rx_buffer[rx_index++] = at91_spi_read(AT91_SPI_RDR);
> if (rx_index>=rx_count)
> {
> // Disable the rcv interrupts from the SPI
> at91_spi_write(AT91_SPI_IDR,AT91_SPI_RDRF);
> }
> }
>
> // we will get more TDRE than we have data to tx, since the rx
data
> // arrives sometime after the tx, and there is no way to tell
which
> // generated the interrupt, so check the tx_count
> if ((spi_status & AT91_SPI_TDRE) && (tx_index
> {
> at91_spi_write(AT91_SPI_TDR,tx_buffer[tx_index++]);
> if (tx_index>=tx_count)
> {
> // Disable the tx interrupts from the SPI
> at91_spi_write(AT91_SPI_IDR,AT91_SPI_TDRE);
> }
> }
> spi_status = at91_spi_read(AT91_SPI_SR);
> }
> if (rx_index>=rx_count)
> wake_up_interruptible(&spi_queue);
> spi_int_count++; // debug
> return IRQ_HANDLED;
> }
>
>
> --------------------------------------------------------------------
----------
> No virus found in this incoming message.
> Checked by AVG Free Edition.
> Version: 7.5.516 / Virus Database: 269.19.19/1258 - Release Date:
2/4/2008 10:10 AM
>

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )Re: Re: SPI and TDRE - Chris DeLise - Feb 4 21:57:45 2008
It's quite a mystery. I figured I was running into "new chip" behavior (I'm using a
sam7xc) but it saw somewhere that all the sam7's have the same SPI design.
I wasn't using CSAAT either because my CPLD's SPI state machine use NCS transitions to
trigger register reads/writes. It was easier than making it count SPCK pulses.
Good luck debugging. It would be interesting to see what your scope trace looks
like.....
Chris
----- Original Message -----
From: jeff_rucker
To: A...@yahoogroups.com
Sent: Monday, February 04, 2008 7:08 PM
Subject: [AT91SAM] Re: SPI and TDRE
Thanks for the comments. This is an AT91 as master application. When
the data gets stuck - either TDRE is low, or RDRF never goes high. I
think it is related to the chip select signals - seems to work better
if I do not use the CSAAT (CS remains high). Still very confusing. I
am going to look at it on a storage scope -
--- In A...@yahoogroups.com, "Chris DeLise"
wrote:
>
> I wish I knew how the interrupt and status register flags were
wired up. In my case hooking up a scope to NCSx, MISO, and MOSI gave
me the needed information. I'm doing bursts of 4-6 words at a time
within a single ISR call, so I spin waiting for TDRE & RDRF. TDRE
goes high nearly immediately after writing a word - probably right
after it transfers into the shift register. RDRF seems to assert
about 1.2 uS after NCS deasserts. It should be immediate, not 60+
MCLK cycle times, and I don't know what causes the delay. Also it
might vary with the baud rate, which is about 80ns per bit (SCBR=4,
48 MHz MCLK).
>
> I'm assuming your At91 is the SPI Master, right? If not all bets
are off. I'd try the scope (a DSO if you've got one) and see if data
is actually being sent. Also, is there the possibility of nested
interrupts, something you probably want to avoid. When your TDRE
stops changing, is it stuck high or low?
>
> Chris
>
> ----- Original Message -----
> From: jrucker@...
> To: A...@yahoogroups.com
> Sent: Monday, February 04, 2008 1:28 PM
> Subject: [AT91SAM] SPI and TDRE
>
>
> I'm doing interrupt I/O on the SPI. Everything seems to work fine
for small transfers (<30 bytes). If I try to transfer 100 bytes, the
TDRE stops changing. I don't see any sign of overflow, but I cannot
see why TDRE would stop changing, when there are still bytes to
write? Also RDRF stops changing.
>
> This is on an embedded linux system, here's the latest version of
the ISR:
>
> wait_queue_head_t spi_queue;
> long spi_status;
> static irqreturn_t spi_interrupt(int irq, void *dev_id)
> {
> spi_status = at91_spi_read(AT91_SPI_SR);
>
> while (
> ((spi_status & AT91_SPI_RDRF) && (rx_index
> ((spi_status & AT91_SPI_TDRE) && (tx_index
> )
> {
> // if there is a byte there, read it
> if ((spi_status & AT91_SPI_RDRF) && (rx_index
> {
> rx_buffer[rx_index++] = at91_spi_read(AT91_SPI_RDR);
> if (rx_index>=rx_count)
> {
> // Disable the rcv interrupts from the SPI
> at91_spi_write(AT91_SPI_IDR,AT91_SPI_RDRF);
> }
> }
>
> // we will get more TDRE than we have data to tx, since the rx
data
> // arrives sometime after the tx, and there is no way to tell
which
> // generated the interrupt, so check the tx_count
> if ((spi_status & AT91_SPI_TDRE) && (tx_index
> {
> at91_spi_write(AT91_SPI_TDR,tx_buffer[tx_index++]);
> if (tx_index>=tx_count)
> {
> // Disable the tx interrupts from the SPI
> at91_spi_write(AT91_SPI_IDR,AT91_SPI_TDRE);
> }
> }
> spi_status = at91_spi_read(AT91_SPI_SR);
> }
> if (rx_index>=rx_count)
> wake_up_interruptible(&spi_queue);
> spi_int_count++; // debug
> return IRQ_HANDLED;
> }
>
>
>
>
>
>
> ----------------------------------------------------------
----------
>
>
> No virus found in this incoming message.
> Checked by AVG Free Edition.
> Version: 7.5.516 / Virus Database: 269.19.19/1258 - Release Date:
2/4/2008 10:10 AM
>
------------------------------------------------------------------------------
No virus found in this incoming message.
Checked by AVG Free Edition.
Version: 7.5.516 / Virus Database: 269.19.19/1258 - Release Date: 2/4/2008 10:10 AM

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )Re: Re: SPI and TDRE - Pavel Bazika - Feb 6 0:16:08 2008
I've discovered recently this behaviour of AT91SAM7X256: when SPI is
configured as master and then enabled, RDRF is zero. But after a short time
it changes to one. RHR register must be read to clear this flag. I've PDC for
SPI also initialized, maybe there is some relationship.
So, maybe this can be a hint to your debugging.
Pavel
Dne Tuesday 05 of February 2008 03:54:20 Chris DeLise napsal(a):
> It's quite a mystery. I figured I was running into "new chip" behavior (I'm
> using a sam7xc) but it saw somewhere that all the sam7's have the same SPI
> design.
>
> I wasn't using CSAAT either because my CPLD's SPI state machine use NCS
> transitions to trigger register reads/writes. It was easier than making it
> count SPCK pulses.
>
> Good luck debugging. It would be interesting to see what your scope trace
> looks like.....
>
> Chris
>
> ----- Original Message -----
> From: jeff_rucker
> To: A...@yahoogroups.com
> Sent: Monday, February 04, 2008 7:08 PM
> Subject: [AT91SAM] Re: SPI and TDRE
> Thanks for the comments. This is an AT91 as master application. When
> the data gets stuck - either TDRE is low, or RDRF never goes high. I
> think it is related to the chip select signals - seems to work better
> if I do not use the CSAAT (CS remains high). Still very confusing. I
> am going to look at it on a storage scope -
>
> --- In A...@yahoogroups.com, "Chris DeLise"
wrote:
> > I wish I knew how the interrupt and status register flags were
>
> wired up. In my case hooking up a scope to NCSx, MISO, and MOSI gave
> me the needed information. I'm doing bursts of 4-6 words at a time
> within a single ISR call, so I spin waiting for TDRE & RDRF. TDRE
> goes high nearly immediately after writing a word - probably right
> after it transfers into the shift register. RDRF seems to assert
> about 1.2 uS after NCS deasserts. It should be immediate, not 60+
> MCLK cycle times, and I don't know what causes the delay. Also it
> might vary with the baud rate, which is about 80ns per bit (SCBR=4,
> 48 MHz MCLK).
>
> > I'm assuming your At91 is the SPI Master, right? If not all bets
>
> are off. I'd try the scope (a DSO if you've got one) and see if data
> is actually being sent. Also, is there the possibility of nested
> interrupts, something you probably want to avoid. When your TDRE
> stops changing, is it stuck high or low?
>
> > Chris
> >
> > ----- Original Message -----
> > From: jrucker@...
> > To: A...@yahoogroups.com
> > Sent: Monday, February 04, 2008 1:28 PM
> > Subject: [AT91SAM] SPI and TDRE
> >
> >
> > I'm doing interrupt I/O on the SPI. Everything seems to work fine
>
> for small transfers (<30 bytes). If I try to transfer 100 bytes, the
> TDRE stops changing. I don't see any sign of overflow, but I cannot
> see why TDRE would stop changing, when there are still bytes to
> write? Also RDRF stops changing.
>
> > This is on an embedded linux system, here's the latest version of
>
> the ISR:
> > wait_queue_head_t spi_queue;
> > long spi_status;
> > static irqreturn_t spi_interrupt(int irq, void *dev_id)
> > {
> > spi_status = at91_spi_read(AT91_SPI_SR);
> >
> > while (
> > ((spi_status & AT91_SPI_RDRF) && (rx_index
> > ((spi_status & AT91_SPI_TDRE) && (tx_index
> > )
> > {
> > // if there is a byte there, read it
> > if ((spi_status & AT91_SPI_RDRF) && (rx_index
> > {
> > rx_buffer[rx_index++] = at91_spi_read(AT91_SPI_RDR);
> > if (rx_index>=rx_count)
> > {
> > // Disable the rcv interrupts from the SPI
> > at91_spi_write(AT91_SPI_IDR,AT91_SPI_RDRF);
> > }
> > }
> >
> > // we will get more TDRE than we have data to tx, since the rx
>
> data
>
> > // arrives sometime after the tx, and there is no way to tell
>
> which
>
> > // generated the interrupt, so check the tx_count
> > if ((spi_status & AT91_SPI_TDRE) && (tx_index
> > {
> > at91_spi_write(AT91_SPI_TDR,tx_buffer[tx_index++]);
> > if (tx_index>=tx_count)
> > {
> > // Disable the tx interrupts from the SPI
> > at91_spi_write(AT91_SPI_IDR,AT91_SPI_TDRE);
> > }
> > }
> > spi_status = at91_spi_read(AT91_SPI_SR);
> > }
> > if (rx_index>=rx_count)
> > wake_up_interruptible(&spi_queue);
> > spi_int_count++; // debug
> > return IRQ_HANDLED;
> > }
> >
> >
> >
> >
> >
> >
> > ----------------------------------------------------------
>
> ----------
>
> > No virus found in this incoming message.
> > Checked by AVG Free Edition.
> > Version: 7.5.516 / Virus Database: 269.19.19/1258 - Release Date:
>
> 2/4/2008 10:10 AM
>
> ---------------------------------------------------------------------------
>---
> No virus found in this incoming message.
> Checked by AVG Free Edition.
> Version: 7.5.516 / Virus Database: 269.19.19/1258 - Release Date:
> 2/4/2008 10:10 AM

(You need to be a member of AT91SAM -- send a blank email to AT91SAM-subscribe@yahoogroups.com )