Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Прерывания и CAN
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Troll
Добрый день (утро, вечер, ночь).

Использую проц 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;
}

Функция для отправки сообщений (приведена не полностью):
Код
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_work вызывается в основном цикле и с заданной периодичностью формирует и отправляет пакеты с данными.

Собственно проблема: если в коде can_work убрать строку (1), то все замечательно. В противном случае возникает "Spurious Interrupt".
Если прерываний от CAN не возникает (изначально не включать прерывания или отключить шину), то тоже все работает (строка (1) не убирается).

Пробовал отключать прерывания в SysAIC, тоже самое.
Если в функции прерывания оставить только верхнии закоментированные строки, то все равно не работает.
Вызов функции can_sendmes можно и закоментировать, ошибка все равно появится.

Дополнительно: передающее устройство присылает несколько десятков пакетов с периодичностью раз в секунду (хотя это влияет только на периодичность появления Spurious Interrupt).

Spurious Interrupt вываливается с периодичностью от 1 до нескольких десятков секунд.

Подскажите в чем может быть проблема? и как ее можно решить?

С уважением.
ssergy
Сделайте процедуру передачи CAN сообщения как SWI функцию.
Troll
Вариант решения.

В мануале прочитал:
Цитата
The CAN interrupt line is connected on one of the internal sources of the Advanced Interrupt
Controller. Using the CAN interrupt requires the AIC to be programmed first. Note that it is not
recommended to use the CAN interrupt line in Edge-sensitive Mode
.

Хотя в разделе к AIC и написано
Цитата
The active level or edge is not programmable for the internal interrupt sources.

Первое утверждение напрягло, решил проверить как будет работать, если изменить параметр "interrupt source type"

в функции инициализации CAN заменил строку:
Код
AT91C_BASE_AIC->AIC_SMR[ID] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | AT91C_AIC_PRIOR_LOWEST; //#define AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL (0<<5)

на:
Код
AT91C_BASE_AIC->AIC_SMR[ID] = (1<<5) | AT91C_AIC_PRIOR_LOWEST;

и случилось чудо.


SRCTYPE Internal Interrupt Sources
0 0 Level Sensitive
0 1 Edge Triggered
1 0 Level Sensitive
1 1 Edge Triggered

Хотя производитель и предупреждает, что "Note that it is not recommended to use the CAN interrupt line in Edge-sensitive Mode", именно в этом режиме уже больше суток работает без ошибок.

Почему происходит ошибка, так и не понял. У меня руки ... или у производителей.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.