johannes_sch wrote on Sunday, November 04, 2007:
I have a problem with the SPI0 interrupt on the AT91SAM7XC256 when using FreeRTOS.
After running the SPI initialization code 1) the SPI ISR is immediately called once, like in the standalone application using no OS, and after serving the ISR the program is continued as usual. But using FreeRTOS the SPI ISR 2) is called and called again in an endless manner, the according Interrupt Pending bit PID4=SPI0 in the AIC Interrupt Pending Register stays set, not even the vPreemptiveTick ISR is called although its priority is the highest. Using an other declaration type of the SPI ISR 3) does not change anything.
The SPI initialization code is called in a separate task, the whole program is derived from the lwIP_Demo_Rowley_ARM7 which works fine in case I disable the SPI interrupt (the EMAC and USB interrupts, which are declarated the same way, work pretty fine).
Any ideas whats going wrong here?
Thanks in advance,
Johannes
1) SPI initialization code:
void SPI0_Init(void)
{
portENTER_CRITICAL();
{
// Configure SPI0 PIOs (CS3=PA15, MISO=PA16, MOSI=PA17, SCK=PA18)
AT91F_PIO_CfgPeriph(AT91C_BASE_PIOA, AT91C_PA15_SPI0_NPCS3 + AT91C_PA16_SPI0_MISO + AT91C_PA17_SPI0_MOSI + AT91C_PA18_SPI0_SPCK, 0);
// Configure PMC by enabling SPI clock
AT91F_SPI0_CfgPMC();
// Configure SPI interrupt
AT91F_AIC_ConfigureIt(AT91C_ID_SPI0, (AT91C_AIC_PRIOR_LOWEST + 0), AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, (void(*)(void)) vSPI0_ISR_Wrapper);
AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SPI0);
// Reset the SPI (note it is possible to reset the SPI even if SPI is disabled)
AT91C_BASE_SPI0->SPI_CR = AT91C_SPI_SWRST; // SPI is in slave mode after reset
AT91C_BASE_SPI0->SPI_IER = AT91C_SPI_RXBUFF + AT91C_SPI_ENDRX;
// Enable SPI
AT91F_SPI_Enable(AT91C_BASE_SPI0);
// Set Mode Register
AT91C_BASE_SPI0->SPI_MR = AT91C_SPI_MSTR + AT91C_SPI_MODFDIS + (AT91C_SPI_PCS & 7<<16); // Master, Fixed Peripheral, CS’s direct connected, Take CS3
// Set Chip Select Register
AT91C_BASE_SPI0->SPI_CSR[3] = AT91C_SPI_CPOL + AT91C_SPI_CSAAT + AT91C_SPI_BITS_8 + (AT91C_SPI_SCBR & 4<<8); // p.278
// Workaround Bug 44.2.5.4 p.668
AT91C_BASE_SPI0->SPI_CSR[0] = AT91C_SPI_CPOL + AT91C_SPI_CSAAT + AT91C_SPI_BITS_8 + (AT91C_SPI_SCBR & 4<<8); // p.278
}
portEXIT_CRITICAL();
}
2) SPI0 ISR type 1
void vSPI0_ISR_Wrapper( void ) __attribute__((naked));
void vSPI0_ISR_Handler( void );
void vSPI0_ISR_Handler( void )
{
volatile unsigned portLONG ulIntStatus;
portBASE_TYPE xSwitchRequired = pdFALSE;
ulIntStatus = AT91C_BASE_SPI0->SPI_SR;
if( ulIntStatus & AT91C_SPI_ENDRX )
{
}
AT91C_BASE_AIC->AIC_EOICR = 0;
if( xSwitchRequired )
{
portYIELD_FROM_ISR();
}
}
void vSPI0_ISR_Wrapper( void )
{
portSAVE_CONTEXT();
vSPI0_ISR_Handler();
portRESTORE_CONTEXT();
}
3) SPI ISR type 2
void vSPI0_ISR_Wrapper( void ) __attribute__((interrupt("IRQ")));
void vSPI0_ISR_Wrapper( void )
{
volatile unsigned portLONG ulIntStatus;
ulIntStatus = AT91C_BASE_SPI0->SPI_SR;
if( ulIntStatus & AT91C_SPI_ENDRX )
{
}
AT91C_BASE_AIC->AIC_EOICR = 0;
}