Использую проц AT91SAM7A3, компилятор gcc
Возникла следующая проблема:
есть функции для работы с CAN. Одна функция обслуживает прерывания по приему пакетов (только прием), копирует принятые пакеты в буфер приема для последующей обработки. Другая функция занимается формированием и отправкой пакетов по CAN.
Функция прерывания:
Код
void can0_handler (void)
{
// printd("*");
// AT91C_BASE_CAN0->CAN_TCR = 0xFFFF;
// AT91C_BASE_AIC->AIC_EOICR = 1;
// return;
int status;
int i;
int adr;
AT91PS_CAN_MB mb;
status = can0.pcan->CAN_SR;
mb = &can0.pcan->CAN_MB0;
for (i = 0; i<8; i++) {
if (status & (1 << i)) {//Принят пакет
adr = (mb->CAN_MB_MID >> 15) & 0xFF;
if ((1<<adr) & can0.device_id) {//Устройство зарегистрированно для обслуживания
can_packet_to_buf (can0.inbuf, can0.inbuf_size, mb->CAN_MB_MID, mb->CAN_MB_MDH, mb->CAN_MB_MDL, (mb->CAN_MB_MSR >> 16)&0xF);
can0.inbuf_update = 1;
}
if ((1<<adr) & can0.device_id_echo) {//Устройство зарегистрированно для ретрансляции
can_packet_to_buf (can1.outbuf, can1.outbuf_size, mb->CAN_MB_MID, mb->CAN_MB_MDH, mb->CAN_MB_MDL, (mb->CAN_MB_MSR >> 16)&0xF);
}
can0.pcan->CAN_TCR = (1 << i); //Освободить центр
}
mb++;
}
AT91C_BASE_AIC->AIC_EOICR = 1;
}
{
// printd("*");
// AT91C_BASE_CAN0->CAN_TCR = 0xFFFF;
// AT91C_BASE_AIC->AIC_EOICR = 1;
// return;
int status;
int i;
int adr;
AT91PS_CAN_MB mb;
status = can0.pcan->CAN_SR;
mb = &can0.pcan->CAN_MB0;
for (i = 0; i<8; i++) {
if (status & (1 << i)) {//Принят пакет
adr = (mb->CAN_MB_MID >> 15) & 0xFF;
if ((1<<adr) & can0.device_id) {//Устройство зарегистрированно для обслуживания
can_packet_to_buf (can0.inbuf, can0.inbuf_size, mb->CAN_MB_MID, mb->CAN_MB_MDH, mb->CAN_MB_MDL, (mb->CAN_MB_MSR >> 16)&0xF);
can0.inbuf_update = 1;
}
if ((1<<adr) & can0.device_id_echo) {//Устройство зарегистрированно для ретрансляции
can_packet_to_buf (can1.outbuf, can1.outbuf_size, mb->CAN_MB_MID, mb->CAN_MB_MDH, mb->CAN_MB_MDL, (mb->CAN_MB_MSR >> 16)&0xF);
}
can0.pcan->CAN_TCR = (1 << i); //Освободить центр
}
mb++;
}
AT91C_BASE_AIC->AIC_EOICR = 1;
}
Функция для отправки сообщений (приведена не полностью):
Код
int can_work (pCAN c)
{
CAN_PACKET packet;
int val;
int mask = canGetMailBoxIntMask(c);
if (c->fmake != NULL) {
if (delta_time(c->tfastreq) > c->rperiod_fast) {
printd("fmake\r\n");
c->tfastreq = jiffies;
}
}
if (c->make != NULL) {
if (delta_time(c->treq) > c->rperiod) {
printd("make\r\n");
c->treq = jiffies;
}
}
c->pcan->CAN_IDR = 0xFF; // - 1 -
can_sendmes (c);
c->pcan->CAN_IER = (mask & 0xFFFF);
return 1;
}
{
CAN_PACKET packet;
int val;
int mask = canGetMailBoxIntMask(c);
if (c->fmake != NULL) {
if (delta_time(c->tfastreq) > c->rperiod_fast) {
printd("fmake\r\n");
c->tfastreq = jiffies;
}
}
if (c->make != NULL) {
if (delta_time(c->treq) > c->rperiod) {
printd("make\r\n");
c->treq = jiffies;
}
}
c->pcan->CAN_IDR = 0xFF; // - 1 -
can_sendmes (c);
c->pcan->CAN_IER = (mask & 0xFFFF);
return 1;
}
Функция can_work вызывается в основном цикле и с заданной периодичностью формирует и отправляет пакеты с данными.
Собственно проблема: если в коде can_work убрать строку (1), то все замечательно. В противном случае возникает "Spurious Interrupt".
Если прерываний от CAN не возникает (изначально не включать прерывания или отключить шину), то тоже все работает (строка (1) не убирается).
Пробовал отключать прерывания в SysAIC, тоже самое.
Если в функции прерывания оставить только верхнии закоментированные строки, то все равно не работает.
Вызов функции can_sendmes можно и закоментировать, ошибка все равно появится.
Дополнительно: передающее устройство присылает несколько десятков пакетов с периодичностью раз в секунду (хотя это влияет только на периодичность появления Spurious Interrupt).
Spurious Interrupt вываливается с периодичностью от 1 до нескольких десятков секунд.
Подскажите в чем может быть проблема? и как ее можно решить?
С уважением.