grzegorzw wrote on Thursday, May 14, 2009:
Thank you for your help. I have still a problem with using semaphore.
I wrote a task:
void vSPI0Task( void *pvParameters )
{
struct tspiIO spiIO;
portBASE_TYPE q;
xSemaphoreTake( xSPI0Semaphore, 0 );
for( ;; )
{
xQueueReceive( xSPIInputQueue, &spiIO, portMAX_DELAY );
SPI_AsyncWriteFirst( AT91C_BASE_SPI0, spiIO.DataToSend , spiIO.DataToSendLen, spiIO.WriteDummy );
SPI_AsyncReadNext( AT91C_BASE_SPI0, spiIO.ReceivedData, spiIO.ReceivedDataLen, spiIO.ReadDummy );
AT91C_BASE_SPI0->SPI_IER = AT91C_SPI_RXBUFF;
PDC_EnableWriteAndRead((AT91S_PDC*)((__u32)(AT91C_BASE_SPI0) + 0x100));
xSemaphoreTake( xSPI0Semaphore, portMAX_DELAY );
xQueueSendToBack( xSPIOutputQueue, &spiIO, portMAX_DELAY );
}
}
And a interrupt subroutine (I am using YAGARTO; interrupts without nesting):
void __attribute__ ((interrupt ("IRQ")))SPI0_irq_handler( void )
{
volatile __u32 spiSr;
portBASE_TYPE xHigherPriorityTaskWoken;
spiSr = AT91C_BASE_SPI0->SPI_SR;
xHigherPriorityTaskWoken = pdFALSE;
if ( spiSr & AT91C_SPI_RXBUFF )
{
AT91C_BASE_SPI0->SPI_IDR = AT91C_SPI_RXBUFF;
xSemaphoreGiveFromISR( xSPI0Semaphore, &xHigherPriorityTaskWoken );
}
AT91C_BASE_AIC->AIC_ISR;
AT91C_BASE_AIC->AIC_EOICR = 0;
if( xHigherPriorityTaskWoken == pdTRUE )
{
portYIELD_FROM_ISR();
}
}
The problem lies in the fact that when the task is blocked in “taking semaphore state”, interrupt can’t give it and the task is “blocked permanently”. In debug mode (step run), when the interrupt comes before “taking semaphore state” and the semaphore is given, program works.