nobody wrote on Wednesday, December 20, 2006:
Hi all,
i am currently working on a project, where i have one task and one ISR.
without the ISR, the task is run continously. But if the interrupt is enabled the task is only run once.
here is my ISR:
void vCANISR( void ) __attribute__((naked));
void vCANISR( void )
{
portENTER_SWITCHING_ISR();
static volatile unsigned long ulIntStatus, ulIntMask, msgstatus;
static volatile unsigned char TEC, REC;
//portBASE_TYPE xSwitchRequired = pdFALSE;
ulIntStatus = AT91C_BASE_CAN->CAN_SR;
ulIntMask= AT91C_BASE_CAN->CAN_IMR;
ulIntStatus &= ulIntMask;
// For debug only:
TEC = (unsigned char)((AT91C_BASE_CAN->CAN_ECR & 0x00FF0000) >> 16);
REC = (unsigned char)(AT91C_BASE_CAN->CAN_ECR & 0x000000FF);
// BUS_OFF
if (ulIntStatus & AT91C_CAN_BOFF)
{
SAM7_CAN_SetCommStatus(AT91C_CAN_BOFF);
}
// ERROR_PASSIVE
if (ulIntStatus & AT91C_CAN_ERRP)
{
SAM7_CAN_SetCommStatus(AT91C_CAN_ERRP);
}
// ERROR_ACTIVE
if (ulIntStatus & AT91C_CAN_ERRA)
{
SAM7_CAN_SetCommStatus(AT91C_CAN_ERRA);
}
if (ulIntStatus & AT91C_CAN_MB0) //TX mailbox
{
msgstatus= AT91C_BASE_CAN->CAN_MB0.CAN_MB_MSR;
if (msgstatus & AT91C_CAN_MRDY)
{
if (SAM7_CAN_IsrTxMsg(&AT91C_BASE_CAN->CAN_MB0))
{
//queue empty
AT91C_BASE_CAN->CAN_IDR = AT91C_CAN_MB0; //Disable Mailbox 0 IRQ
}
else
{
//send next msg
//AT91C_BASE_CAN->CAN_TCR= AT91C_CAN_MB0; // Transfer request
AT91C_BASE_CAN->CAN_MB0.CAN_MB_MCR = AT91C_CAN_MTCR; // Transfer request
}
}
//xSwitchRequired = xSemaphoreGiveFromISR( xSemaphore, pdFALSE );
}
if (ulIntStatus & AT91C_CAN_MB1) //RX mailbox
{
msgstatus= AT91C_BASE_CAN->CAN_MB1.CAN_MB_MSR;
if (msgstatus & AT91C_CAN_MRDY)
{
SAM7_CAN_IsrRxMsg(&AT91C_BASE_CAN->CAN_MB1);
AT91C_BASE_CAN->CAN_MB1.CAN_MB_MCR = AT91C_CAN_MTCR; // Transfer request
}
//xSwitchRequired = xSemaphoreGiveFromISR( xSemaphore, pdFALSE );
}
if (ulIntStatus & AT91C_CAN_MB2) //RX mailbox
{
msgstatus= AT91C_BASE_CAN->CAN_MB2.CAN_MB_MSR;
if (msgstatus & AT91C_CAN_MRDY)
{
SAM7_CAN_IsrRxMsg(&AT91C_BASE_CAN->CAN_MB2);
AT91C_BASE_CAN->CAN_MB2.CAN_MB_MCR = AT91C_CAN_MTCR; // Transfer request
}
//xSwitchRequired = xSemaphoreGiveFromISR( xSemaphore, pdFALSE );
}
// Clear the interrupt.
AT91C_BASE_AIC->AIC_EOICR = 0;
portEXIT_SWITCHING_ISR( 0 );
//portEXIT_SWITCHING_ISR( xSwitchRequired );
}
NOTE: It is not necessary for the ISR to switch context. This is only done because of earlier experience with the lwip demo for the sam7x where i had a timerISR which would halt program execution if the above syntax weren’t implemented (portEXIT_SWITCHING_ISR() and portEXIT_SWITCHING_ISR( 0 )).
is there another way to do this differently ?