lpc2148: wiered SSP behaviour or hardware bug???
2005-12-13 by diwilru
Hi Fellows,
Something strange happens when I try to use SSP in lpc2148.
So, I initiate SSP as per spi1_init(2,11) in SPI mode with tx FIFO half empty interrupts
enabled (see the code below).
Then I start to transfer bytes over SPI.
The first portion of the data until tx FIFO is empty being transfered Ok. Then
I expect SPI1 interrupt routine should be called, but it never happens. I actually
expect ISR being called when tx FIFO is half empty in order to stuff it with more data.
I got also timer interrupts configured on compare match and it works.
However, if I configure SPI1 interrupts having higher priority than timer's ones none of
interrupts happen. Nevertheless SPI1's tx FIFO being emptied.
If I assign SPI1 to default vector, SPI1 generates interrupts, but...
RFF bit is always 1 regardless of the number of words I write to SSPDR.
MCU falls into SPI ISR and never exits from it.
The question is:
Is this a hardware bug or did I miss something?
MCU works as expected if timer0, I2C and UART0 interrupts enabled.
Compiler is not an issue - the binary code is fine (no inter-working , arm mode only)
None of unexpected interrupts happen.
Pull-up at SSEL1 does not make any difference.
Thanks in advance
Dmitry.
===================================================
void __attribute__((naked)) spi1_ISR(void);
void
spi1_init(int divide, int prio)
{
int *veccntl = (int *)0xFFFFF200 + prio;
int *vecaddr = (int *)0xFFFFF100 + prio;
PINSEL1 |= (2<<2) | (2<<4) | (2<<6) | (2<<8);
SSPCR0 = (0xf<<0) | (1<<6) | (1<<7); // CPOL == 1; CHPA == 1, 16-bit
transfer
SSPCPSR = divide;
SSPIMSC = 0x8; // tx FIFO half empty
VICIntSelect &= ~VIC_BIT(VIC_SPI1); // SPI1 selected as IRQ
VICIntEnable |= VIC_BIT(VIC_SPI1); // SPI1 interrupt enabled
*veccntl = VIC_ENABLE | VIC_SPI1;
*vecaddr = (uint32_t)spi1_ISR; // address of the ISR
SSPCR1 = 2 ;
}
void __attribute__((naked)) spi1_ISR(void)
{
unsigned int why;
short dummy;
ISR_ENTRY(); // clear rcv bit
why = SSPMIS;
if(why == 8)
SSPDR = 0x1111;
if(why != 8)
SSPICR = 3;
VICVectAddr = 0x00000000; // Clear interrupt in
ISR_EXIT();
}