EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

interfacing using SPI on LPC2148

Started by lucky_suhas August 28, 2011
--- In l..., "lucky_suhas" wrote:
> so what an interrupt would do is to carryout the ISR in the background while the rest of the code execution continues?
Foreground and Background are from the point of view of the main task.

If you are talking to someone, you may consider that the Foreground task.

Some else comes along and taps you on the shoulder, you SUSPEND the main task and SERVICE the Background task.

If you spend too much time on the Background task, the Foreground task may crash (walk away).

After you finish with the Background task, you RESUME the foreground task.

As a beginner I would suggest not using Interrupts until you have written code for all the peripherals on the CPU you are using.

The LPC family is fast enough to use without any interrupts.
( even most 8-bit processors are fast enough )

Once you have learned how to use them, adding interrupts will be much easier.

don

An Engineer's Guide to the LPC2100 Series

--- In l..., "lucky_suhas" wrote:
> so what an interrupt would do is to carryout the ISR in the background while the rest of the code execution continues?

A timer interrupt might increment a clock or it might be a time tick for an RTOS.

A character received interrupt might grab the char from the UART and stick it in a circular buffer. The main program would simply grab chars from the circular buffer rather than deal with the UART.

A character output interrupt might grab a character from a circular buffer and send it out over a serial port. The main program would simply stuff characters into the buffer rather than concern itself with handling the UART.

And so on...

>
> regarding the ISR address:
>
> i have noticed
> 1. VICVectAddr=0;
> /*is used at the end of the code to reset the VIC in the __irq*/
>
> 2. VICVectAddr0= (unsigned int) &name_of_ISR;
> /* is used in the initialization of the particular function*/
>
> in point 1. what is the meaning of resetting the VIC? addr register is only to store the ISR address and more over it should have a suffix of 0-15, right?

It acknowledges that the active interrupt is complete. The VIC knows which interrupt is active so it isn't necessary to specify which interrupt to acknowledge.

Remember that the VIC is a priority based controller. This is important once interrupt nesting is enabled.

It's also worth knowing that nested interrupts are a problem unless you write some additional 'wrapper' code (usually in crt.s) to handle the nesting. Don't worry about it right now because it won't happen. Once an interrupt is started, further interrupts are disabled so even higher priority interrupts are ignored. -- remember this! --

There are (or at least, were) problems with the GNU toolchain and interrupt code. Once you find out how to write the interrupt wrapper in crt.s, you won't use any special __attributes__ when you write the handler. All handlers will be ordinary C functions. This is VERY NICE and worth the cost of researching wrappers.

Here is some reference material:
http://www.nxp.com/documents/application_note/AN10381.pdf

You can search the group archives for 'wrapper'. Code is available around here somewhere because that's where I got it.

But you only need it if you decide to use nested interrupts and those are usually only required if you actually use the priority scheme.
>
> in point 2. why is it necessary the data type be given? is it possible the compiler might assign a different type to a Lvalue of the function?
Probably not but C programmers are a paranoid bunch (with very good reason). It is better to tell the compiler what to do than try to find out what it did. It's called 'defensive programming'. Of course you could simply eliminate the cast and see what happens. Maybe the compiler will generate a warning or an error. But that might depend on compiler switches... It's better to use the cast.

Richard

Interrupts allow your program to handle events faster than polling all
possible events to handle them.

DaveS

On Mon, Aug 29, 2011 at 6:48 AM, lucky_suhas wrote:

> **
>
> thanks, is it necessary i use interrupts in my code? not only in this case,
> i am asking in general. Most of the codes that i have come across for
> UART,SPI,I2C, EEPROM, etc., have made use of interrupts.
> is it just a better programming technique or is it a necessary one?
>
> --- In l..., "rtstofer" wrote:
> >
> >
> >
> > --- In l..., "lucky_suhas" wrote:
> > >
> > > HI again,
> > >
> > > I have been trying to learn programming using the LPC2148.
> > > Thanks to all the people who replied and helped with my ADC code.
> > > I am taking the help of some example codes i found online. but with
> regard to SPI there doesn't seem to be any examples around. although i found
> one that interfaces SPI to SD card. it was a little difficult to understand.
> i would like a generalized code on using SPI.
> > >
> > > i am not asking you to give me the code.. if anyone could suggest me on
> the various functions that i should write and the process flow. like in ADC
> i had to write two functions
> > > 1.initialization the control register
> > > 2.then i had to read the data register.
> >
> >
> >
> >
> > For SPI to work, you send a byte or short (8 or 16 bit) out while the
> hardware simultaneously clocks in a similar data item.
> >
> > The following code is set up for 16 bit transfers. SPI0_send sends out a
> 16 bit unsigned short and returns the unsigned short that was clocked in.
> >
> > #include "lpc214x.h"
> > #include "spi.h"
> >
> > /*
> > * P0.4 => SCK connect to AD7327 SCLK
> > * P0.5 => MISO connect to AD7327 DOUT
> > * P0.6 => MOSI connect to AD7327 DIN
> > * P0.7 => SSEL connect to AD7327 CS'
> > */
> >
> > #define SSEL (1 << 7)
> > #define SPI_SPIE (0x00000080)
> > #define SPI_LSBF (0x00000040)
> > #define SPI_MSTR (0x00000020)
> > #define SPI_CPOL (0x00000010)
> > #define SPI_CPHA (0x00000008)
> > #define SPI_BitEnable (0x00000004)
> > #define SPI_Bits (0x00000000)
> >
> > #define SPI_SPIF (0x00000080)
> >
> > #define SPI_DIVIDER (8)
> >
> > /*
> > * Set up SPI0 as a master with CPOL = 1, CPHA = 0 and 16 bit transfers.
> > * Force P0.7 to GPIO, set it for output and set it high
> > */
> > void SPI0_init(void)
> > {
> > PINSEL0 |= 0x00001500;
> > PINSEL0 &= ~0x0000C000;
> > IOSET0 = SSEL;
> > IODIR0 |= SSEL;
> >
> > S0SPCR = SPI_MSTR | SPI_CPOL | SPI_BitEnable | SPI_Bits;
> > S0SPCCR = SPI_DIVIDER;
> > }
> >
> > /*
> > * Send value to ADC and return value shifted in.
> > */
> > unsigned short SPI0_Send(const unsigned short value)
> > {
> > IOCLR0 = SSEL;
> > S0SPDR = value;
> > while (!(S0SPSR & SPI_SPIF))
> > ;
> > IOSET0 = SSEL;
> > return (S0SPDR);
> > }
> >
> > You can always just connect MOSI and MISO externally (a jumper wire) and
> test by looking at what is received versus what it sent. They should be
> identical.
> >
> > Richard
> >
>
--- In l..., "rtstofer" wrote:
>
> It acknowledges that the active interrupt is complete. The VIC knows which interrupt is active so it isn't necessary to specify which interrupt to acknowledge.
I omitted the part where the ISR must clear the appropriate interrupt flag in the peripheral that is being serviced. It is not sufficient to simply acknowledge the intterupt for the VIC.

There may be a number of interrupt flags in any given peripheral. Your ISR has to handle all possibilities and clear each of the individual flags.

If you don't clear the flag(s) in the peripheral, you will get another interrupt.

Some flags are cleared automatically when certain registers are read. Read over the section on UART0 and look at table 105. The right column shows how each potential interrupt is cleared. None of them require deliberate writing of a register bit to clear a flag.

Richard


The 2024 Embedded Online Conference