EmbeddedRelated.com
Forums

LPC2148 SPI and SSP behaviour

Started by Jan Thogersen May 1, 2006
Hi,

It's now my second week in the presence of a Phillips ARM processor and
I must say that it really rock's! However, due to my lack of experience
with this wonder I face some problems getting the thing to obey all my
orders :-)

I really appreciate the effort people are making in this mailing list to
help each other and when I gain some experience I will do my best to
repay my debt!

Playing with the SPI and SSP module left me with a couple of questions...

SPI speed:
I initialized the SPI module and to my surprise the clock was only 7.5
MHz even though the core was running 60MHz. Then I saw in the datasheet
that the SPI module only runs at 1/8 of the core speed. Can that really
be true and why is that? 7.5MHz at max is close to useless in these days.

SSP interrupts:
In my design I have a DAC connected to the SSP module. The DAC needs 24
bits for each conversion. Therefore I need to pull the SS low then send
the 24bits and wait for the SSP modul to enter idle state (Checking the
busy flag) then raise the SS again. Now I want to get this process to
run automatically in interrupts. So I need to get an interrupt when the
SSP is done... But it doesn't seem to be possible, the only flag
available is the timeout flag and that is issued 32 clocks after the
transmission ends. Which leaves me with a bit gab in the transmission.
Is the timeout flag my only friend in this situation?

Interrupt problem:
I got timer vectored interrupts up and running just fine, however the
SSP just won't request any interrupts. Here is a snippet of my code.
Maybe it's very obvious what I'm doing wrong, but I can't see it.
As I said the other interrupts are working just fine, so I really can't
see why the SSP interrupts won't work.
I'm using the CrossWorks compiler.

static void SSP_isr(void) __attribute__ ((interrupt ("IRQ")));
static void SSP_isr(void) {
static uint8 ting;

for(;;);

VICVectAddr = 0;
}

void SSP_Init(void) {
SSPCR0 = (0 << 8) | 0x47; // Set phases and baud rate
SSPCR1 = 0x02; // Enable SSP module
SSPCPSR = 0x02; // Clock Prescale Register
PINSEL1 |= 0x000002A8; // Map the SPI functionality to pins

SSPIMSC = SSPIMSC_RORIM |SSPIMSC_RTIM | SSPIMSC_RXIM | SSPIMSC_TXIM;
// Enable the interrupts

VICIntSelect &= ~0x00000800; // Map SSP to "IRQ"
VICIntEnable = 0x00000800; // Enable the SSP interrupt in the VIC
VICVectCntl2 = 0x0000002B; // Map SSP interrupt to VIC slot 2
VICVectAddr2 = (unsigned int) SSP_isr; // Assign the interrupt handler
}

And one last question... is it possible to shift between the ARM and
thumb mode realtime. Is it possible to make some of my functions in
thumb mode and some in ARM mode? Any pragma to control the mode?

Thanks in advance! Hope that I have made some worthy questions!

Best regards
Jan Thogersen

An Engineer's Guide to the LPC2100 Series

--- In l..., Jan Thogersen wrote:
>
> Hi,
>
> It's now my second week in the presence of a Phillips ARM processor
and
> I must say that it really rock's! However, due to my lack of
experience
> with this wonder I face some problems getting the thing to obey all
my
> orders :-)
>
> I really appreciate the effort people are making in this mailing
list to
> help each other and when I gain some experience I will do my best
to
> repay my debt!
>
> Playing with the SPI and SSP module left me with a couple of
questions...
>
> SPI speed:
> I initialized the SPI module and to my surprise the clock was only
7.5
> MHz even though the core was running 60MHz. Then I saw in the
datasheet
> that the SPI module only runs at 1/8 of the core speed. Can that
really
> be true and why is that? 7.5MHz at max is close to useless in these
days.
>
> SSP interrupts:
> In my design I have a DAC connected to the SSP module. The DAC
needs 24
> bits for each conversion. Therefore I need to pull the SS low then
send
> the 24bits and wait for the SSP modul to enter idle state (Checking
the
> busy flag) then raise the SS again. Now I want to get this process
to
> run automatically in interrupts. So I need to get an interrupt when
the
> SSP is done... But it doesn't seem to be possible, the only flag
> available is the timeout flag and that is issued 32 clocks after
the
> transmission ends. Which leaves me with a bit gab in the
transmission.
> Is the timeout flag my only friend in this situation?
>
> Interrupt problem:
> I got timer vectored interrupts up and running just fine, however
the
> SSP just won't request any interrupts. Here is a snippet of my
code.
> Maybe it's very obvious what I'm doing wrong, but I can't see it.
> As I said the other interrupts are working just fine, so I really
can't
> see why the SSP interrupts won't work.
> I'm using the CrossWorks compiler.
>
> static void SSP_isr(void) __attribute__ ((interrupt ("IRQ")));
> static void SSP_isr(void) {
> static uint8 ting;
>
> for(;;);
>
> VICVectAddr = 0;
> }
>
> void SSP_Init(void) {
> SSPCR0 = (0 << 8) | 0x47; // Set phases and baud rate
> SSPCR1 = 0x02; // Enable SSP module
> SSPCPSR = 0x02; // Clock Prescale Register
> PINSEL1 |= 0x000002A8; // Map the SPI functionality to pins
>
> SSPIMSC = SSPIMSC_RORIM |SSPIMSC_RTIM | SSPIMSC_RXIM |
SSPIMSC_TXIM;
> // Enable the interrupts
>
> VICIntSelect &= ~0x00000800; // Map SSP to "IRQ"
> VICIntEnable = 0x00000800; // Enable the SSP interrupt in
the VIC
> VICVectCntl2 = 0x0000002B; // Map SSP interrupt to VIC slot 2
> VICVectAddr2 = (unsigned int) SSP_isr; // Assign the interrupt
handler
> }
>
> And one last question... is it possible to shift between the ARM
and
> thumb mode realtime. Is it possible to make some of my functions in
> thumb mode and some in ARM mode? Any pragma to control the mode?
>
> Thanks in advance! Hope that I have made some worthy questions!
>
> Best regards
> Jan Thogersen
>

Hi Jan,
Many options on the SSP, but one I have used several times in a
similar situation is to trigger an interrupt using SS. You can
connect the SS signal to an external int pin. Not the most elegant
and it uses an extra pin, but it seperates the interrupt mechanism
from the SSP module (up to you to decide if that is a good thing in
your app.) Also, if you are generating your SS signal from the LPC
timers you can use the timer interrupts.

Regards,
Ian
Hi Jan,
> Many options on the SSP, but one I have used several times in a
> similar situation is to trigger an interrupt using SS. You can
> connect the SS signal to an external int pin. Not the most elegant
> and it uses an extra pin, but it seperates the interrupt mechanism
> from the SSP module (up to you to decide if that is a good thing in
> your app.) Also, if you are generating your SS signal from the LPC
> timers you can use the timer interrupts.
>
Hey,
Thanks!
That was an interesting way of solving it! Now why didn't I think of
that :-)
I'm just wondering why Phillips didn't make it possible to trap the busy
flag.
There is plenty of space left in the SSP interrupt flag register. It
just seems like a feature that
a lot of developers miss.

regards
.
> >
> > SPI speed:
> > I initialized the SPI module and to my surprise the clock was only
> 7.5
> > MHz even though the core was running 60MHz. Then I saw in the
> datasheet
> > that the SPI module only runs at 1/8 of the core speed. Can that
> really
> > be true and why is that? 7.5MHz at max is close to useless in these
> days.

Why would you think that the User's Manual, which is quite explicit,
is wrong? The same limitation on SPI speed occurs on multiple devices
such as the LPC2103, 2106 and 2148.

> >
> > SSP interrupts:
> > In my design I have a DAC connected to the SSP module. The DAC
> needs 24
> > bits for each conversion. Therefore I need to pull the SS low then
> send
> > the 24bits and wait for the SSP modul to enter idle state (Checking
> the
> > busy flag) then raise the SS again. Now I want to get this process
> to
> > run automatically in interrupts. So I need to get an interrupt when
> the
> > SSP is done... But it doesn't seem to be possible, the only flag
> > available is the timeout flag and that is issued 32 clocks after
> the
> > transmission ends. Which leaves me with a bit gab in the
> transmission.
> > Is the timeout flag my only friend in this situation?

There are FIFO flags that indicate when the buffer is half empty
(transmit) or half full (receive).

None of these may help where you want to specifically control the
conversion, presumably as a function of time. So, how do you
determine when to send data to the DAC?

> >
> > Interrupt problem:
> > I got timer vectored interrupts up and running just fine, however
> the
> > SSP just won't request any interrupts. Here is a snippet of my
> code.
> > Maybe it's very obvious what I'm doing wrong, but I can't see it.
> > As I said the other interrupts are working just fine, so I really
> can't
> > see why the SSP interrupts won't work.
> > I'm using the CrossWorks compiler.
> >
> > static void SSP_isr(void) __attribute__ ((interrupt ("IRQ")));
I would think you would want to move SSP_isr away from the one and
only IRQ interrupt entry point by defining:

void SSP_isr(void) __attribute__ ((interrupt));

> > static void SSP_isr(void) {
> > static uint8 ting;
> >
> > for(;;);
> >
> > VICVectAddr = 0;
> > }
> >
> > void SSP_Init(void) {
> > SSPCR0 = (0 << 8) | 0x47; // Set phases and baud rate
> > SSPCR1 = 0x02; // Enable SSP module
> > SSPCPSR = 0x02; // Clock Prescale Register
> > PINSEL1 |= 0x000002A8; // Map the SPI functionality to pins
> >
> > SSPIMSC = SSPIMSC_RORIM |SSPIMSC_RTIM | SSPIMSC_RXIM |
> SSPIMSC_TXIM;
> > // Enable the interrupts
> >
> > VICIntSelect &= ~0x00000800; // Map SSP to "IRQ"
> > VICIntEnable = 0x00000800; // Enable the SSP interrupt in
> the VIC
> > VICVectCntl2 = 0x0000002B; // Map SSP interrupt to VIC slot 2
> > VICVectAddr2 = (unsigned int) SSP_isr; // Assign the interrupt
> handler
> > }
> >
> > And one last question... is it possible to shift between the ARM
> and
> > thumb mode realtime. Is it possible to make some of my functions in
> > thumb mode and some in ARM mode? Any pragma to control the mode?
> >
> > Thanks in advance! Hope that I have made some worthy questions!
> >
> > Best regards
> > Jan Thogersen
> > Hi Jan,
> Many options on the SSP, but one I have used several times in a
> similar situation is to trigger an interrupt using SS. You can
> connect the SS signal to an external int pin. Not the most elegant
> and it uses an extra pin, but it seperates the interrupt mechanism
> from the SSP module (up to you to decide if that is a good thing in
> your app.) Also, if you are generating your SS signal from the LPC
> timers you can use the timer interrupts.
>
> Regards,
> Ian
>