Перейти к содержанию
    

прерывания от таймеров в SAM

Ура! Огромное спасибо всем за помощь! Срабатывает, и не раз =) Тему можно закрыть.

ЗЫ

Сегодня я самый счастливый нуб на свете =)

Изменено пользователем AVR

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Точно, всё аналогично AVRкам, тоже надо добавить прагму vector = 0x18 перед обработчиком IRQ =)

Что-то меня настораживает. Все же на 0x18 должно быть ldr pc, [pc, #-0xf20], или что-нибудь не столь лаконичное, но аналогичное по смыслу.

А pragma vector = 0x18 - какая-то вредная штуковина, ИМХО.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что-то меня настораживает. Все же на 0x18 должно быть ldr pc, [pc, #-0xf20], или что-нибудь не столь лаконичное, но аналогичное по смыслу.

А pragma vector = 0x18 - какая-то вредная штуковина, ИМХО.

Не, всё на самом деле нормально, теперь по адресу 0x18 висит инструкция ldr pc, [pc, #+24]

А использование pragma vector = 0x18 прописано в справке на iccarm для обработчиков прерываний.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я тоже начинал с такого варианта прерываний. Он простой и файл стартап не нужно исправлять. Особенно если в системе только одно прерывание от таймера, то лучше вообще не мудрить.

Изменено пользователем GetSmart

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну если так проще, тогда ладно.

 

P.S. Интересно, кто-нибудь еще использовал в своих проектах RTT?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

P.S. Интересно, кто-нибудь еще использовал в своих проектах RTT?

У меня ещё вопрос возник: почему atmel называет это риалтайм таймером, если к нему подается только источник SLCK, частота которого только приблизительно равна 32768 Гц. Часы на таком явно не организовать... Есть ли возможность настроить на другой источник тактов?

ЗЫ

Можно ли и как заставить SAM7S пропускать MCK на один из выходов PIO, чтобы, например, тактировать внешнюю периферию такую как CPLD?

ЗЫЗЫ

Посоветуйте, пожалуйста, какую-нибудь микросхему SRAM в DIP корпусе на 64 КБайт.

Изменено пользователем AVR

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть ли возможность настроить на другой источник тактов?

Нет.

 

Можно ли и как заставить SAM7S пропускать MCK на один из выходов PIO, чтобы, например, тактировать внешнюю периферию такую как CPLD?

Можно. Почитайте про Programmable Clock Output в PMC.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что нужно сделать, чтобы срабатывали несколько разных перерываний? Ведь тогда получается разные обработчики должны начинаться на 0x18, а одновременно это невозможно... Для чего тогда нужен AIC, если он сам автоматом не загружает в PC адрес нужно обработчика... :blink:

Изменено пользователем AVR

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Что нужно сделать, чтобы срабатывали несколько разных перерываний? Ведь тогда получается разные обработчики должны начинаться на 0x18, а одновременно это невозможно... Для чего тогда нужен AIC, если он сам автоматом не загружает в PC адрес нужно обработчика... :blink:

__arm __irq void IRQ_Handler(void) {
     void (*AT91C_AIC_IVR)();
     AT91C_BASE_AIC->AT91C_AIC_EOICR = 0;
}

что-то вроде этого. Или же по адресу 0x18 в асмовом файле разместить

        LDR        PC, AT91C_AIC_IVR

и каждый обработчик оформлять как __arm __irq не забывая в конце каждого обработчика вставлять AT91C_BASE_AIC->AT91C_AIC_EOICR = 0;

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Прошу прощения, что поднимаю старую тему и за очередной глупый для Вашего внимания вопрос, но ... объясните мне пожалуйста, в чем причина?

Использую таймер и он в обработчике виснет:

 

 

void channal (void)

{

for (int chan=0;chan<9;chan++){

while (!((AT91C_BASE_SPI->SPI_SR) & AT91C_SPI_TXEMPTY));

AT91F_SPI_CfgPCS(AT91C_BASE_SPI,0);

AT91F_SPI_PutChar (AT91C_BASE_SPI, SPI_SEND[chan],0 );

while (!((AT91C_BASE_SPI->SPI_SR) & AT91C_SPI_TXEMPTY));

AT91F_SPI_CfgPCS(AT91C_BASE_SPI,0);

AT91F_SPI_PutChar (AT91C_BASE_SPI, SPI_SEND[chan],0 );

while (!((AT91C_BASE_SPI->SPI_SR) & AT91C_SPI_TXEMPTY));

AT91F_SPI_CfgPCS(AT91C_BASE_SPI,0);

AT91F_SPI_PutChar (AT91C_BASE_SPI, SPI_SEND[chan],0 );

while (!((AT91C_BASE_SPI->SPI_SR) & AT91C_SPI_TXEMPTY));

tin=AT91F_SPI_GetChar(AT91C_BASE_SPI);

DATA[shet_i][chan]=tin & 0x0FFE;

 

 

switch (BUFF_STATUS[5]){

case 0x01:

DATA[shet_i][chan]=filt_niz_chas(DATA[shet_i][chan]);

break;

 

case 0x10:

DATA[shet_i][chan]=filt_vis_chas(DATA[shet_i][chan]);

break;

 

case 0x11:

DATA[shet_i][chan]=filt_niz_chas(DATA[shet_i][chan]);

DATA[shet_i][chan]=filt_vis_chas(DATA[shet_i][chan]);

break;

}

 

if (DATA[shet_i][chan]>max_data[chan]) max_data[chan]=DATA[shet_i][chan]; //находим максимум

 

BUFF_STATUS[(chan+7)*2+1]=max_data[chan];

BUFF_STATUS[(chan+7)*2]=max_data[chan] >> 8;

}

 

 

 

}

 

 

void Periodic_Interval_Timer_handler (void)

{

unsigned int status;

 

status = AT91C_BASE_PITC->PITC_PIVR;

status =status;

 

AT91F_PIO_ClearOutput(AT91C_BASE_PIOA, LED1);

spiflag=1;

channal();

AT91C_BASE_AIC->AIC_EOICR=0x00;

AT91F_PIO_SetOutput(AT91C_BASE_PIOA, LED1);

}

 

 

Инициализация таймера:

AT91F_PMC_EnablePeriphClock ( AT91C_BASE_PMC, 1 << AT91C_ID_PIOA ) ;

AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC,

AT91C_ID_SYS,

RTTC_INTERRUPT_LEVEL,

AT91C_AIC_SRCTYPE_EXT_LOW_LEVEL,

Periodic_Interval_Timer_handler);

AT91C_BASE_PITC->PITC_PIMR = AT91C_PITC_PITEN | AT91C_PITC_PITIEN | PIV_2_MS;

AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_SYS);

 

 

 

PIV_2_MS=467 //по моим подсчетам должно быть в районе 156 мксек, верно?

 

 

Вобщем при запуске программы лампочка загорается и почти мгновенно тухнет. Еле заметишь, вобщем такое ощущение что заходит один раз в прерывание и там остается, выполнив все. Частота SPI 15 МГц. По приблизительным подсчетам вся программа должна успевать выполнятся до следующего прерывания. Или я ошибаюсь? И вобще нужны ли ожидания перед отправкой 16-ти бит в SPI? Может эти вайлы вобще нафиг выкинуть? На shet_i не обращайте внимания, он обрабатывается в другой части программы, до которой не доходит.

Если закоментировать строку channal() то все работает .... то есть лампочка тускло так горит ....

Ставил __irq компилятор выдает ошибку: Error[Pe167]: argument of type "void (__arm __irq __atpcs *)(void)" is incompatible with parameter of type "void (*)()"

Прошу сильно не ругаться, и смеятся не до колик, собственно я еще полный ламер, а даташит читать - с английским не важнец .... Кстати, может кто нить подскажет где можно в Екатеринбурге купить книжку по SAM7 на РУССКОМ? Или может через инет заказать ....

Изменено пользователем Timofey

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если закоментировать строку channal() то все работает .... то есть лампочка тускло так горит ....

Ставил __irq компилятор выдает ошибку: Error[Pe167]: argument of type "void (__arm __irq __atpcs *)(void)" is incompatible with parameter of type "void (*)()"

Я, конечно, и сам ламер, но всё же есть некоторые догадки...

По всей видимости, функция "channal" выполняется слишком долго (вообще помещать такие страшные функции в обработчики это не очень хорошо :) ), попробуйте вынести её в основной цикл программы, а при срабатывании прерывания по таймеру просто инкрементируйте некую переменную, которая сообщит программе в основном цикле о том, что нужно вызвать channal (и при этом декрементируйте эту переменную). Если эта переменная будет больше единицы, значит channal выполняется дольше чем нужно.

ЗЫ

Попробуйте добавить такой код. Саму же функцию обработчика определенного прерывания нужно оформить как обычную функцию без __irq

#pragma vector = 0x18
__irq __arm void IRQ()
{
    void (*IRQ_Handler)() = (void(*)())AT91C_BASE_AIC->AIC_IVR;
    IRQ_Handler();
    AT91C_BASE_AIC->AIC_EOICR = 0;
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По всей видимости, функция "channal" выполняется слишком долго (вообще помещать такие страшные функции в обработчики это не очень хорошо :) ), попробуйте вынести её в основной цикл программы, а при срабатывании прерывания по таймеру просто инкрементируйте некую переменную, которая сообщит программе в основном цикле о том, что нужно вызвать channal (и при этом декрементируйте эту переменную).

За код спасибо. На счет того что в прерывании лучше вобще ничего делать, я знаю, но дело в том что больше никак. Мне нужно все это делать именно в прерывании ... В этом то и фишка ...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Исходные данные

 

Инициализация

void init_interrupt_PIT(t_uint32 Interval, void InterruptHandler(void))
{
    volatile t_uint32 temp;

//    if (InterruptHandler != NULL)
//    {
        AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SYS, 
                              PIT_PRIORITY, AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE,
                              InterruptHandler);
//    }
//    else
//    {
//        AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SYS, 
//                              PIT_PRIORITY, AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE,
//                              (void(*)(void))ih_PIT);
//    }
    temp = AT91C_BASE_PITC->PITC_PIVR;
    AT91C_BASE_PITC->PITC_PIMR = temp;

    AT91C_BASE_PITC->PITC_PIMR = (Interval & AT91C_PITC_PIV)
                               |
                               AT91C_PITC_PITEN
                               |
                               AT91C_PITC_PITIEN;
}

Вызов

    init_interrupt_PIT(0x000000FF, (void(*)(void))ih_fromPIT);

Обработчик

void ih_fromPIT(void) __irq
{
    if (AT91C_BASE_PITC->PITC_PISR & AT91C_PITC_PITS )
    {
        g_systemSignals.displayStart = 1;        
    }    
    /* îáðàáîò÷èê çàâåðøåí */
    AT91C_BASE_AIC->AIC_EOICR = 0;
}

Других обработчиков от системного контроллера нет.

 

Вопрос. Почему обработчик ни разу не вызывается? Что я не понимаю?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кто-нибудь может скинуть рабочий код для PIT?

Странно но заработало вот так (я там кстати включить прерывание забыл :blush: )

void init_interrupt_PIT(t_uint32 Interval, void InterruptHandler(void))
{
    if (InterruptHandler != NULL)
    {
        AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SYS, 
                              PIT_PRIORITY, AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE,
                              InterruptHandler);
    }
    else
    {
        AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SYS, 
                              PIT_PRIORITY, AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE,
                              (void(*)(void))ih_PIT);
    }
    AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS);

    AT91C_BASE_PITC->PITC_PIMR = (((__int64)(MCK / 16) * Interval / 1000000) & AT91C_PITC_PIV)
                               |
                               AT91C_PITC_PITEN
                               |
                               AT91C_PITC_PITIEN;
}

void ih_fromPIT(void) __irq
{
    volatile t_uint32 temp = 0;
    if (AT91C_BASE_PITC->PITC_PISR & AT91C_PITC_PITS )
    {
        g_systemSignals.displayStart = 1;
        temp = AT91C_BASE_PITC->PITC_PIVR;
    }    
    /* îáðàáîò÷èê çàâåðøåí */
    AT91C_BASE_AIC->AIC_EOICR = temp;
}

При этом если не читать PIVR флаг прерывания не снимается.

Отсюда вопрос каким образом от данного таймера получить интервал прерываний больший 20-разрядной части и зачем вообще нужен PICNT?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...