|
|
  |
прерывания от таймеров в SAM, опять затупил :( |
|
|
|
Jun 26 2006, 09:41
|

Дух погибшего транзистора
   
Группа: Свой
Сообщений: 877
Регистрация: 6-09-05
Из: Москва
Пользователь №: 8 288

|
Что-то с самом у меня не клеится. Не пионимаю как организовать прерывание по переполнению таймера. вобщем что понятно. нужно проинициализировать aic и поставить таймер в режим сравнения. в регистр сравнения rc таймера записать максимальное значение 0xFFFF Код void set_timer_channel1_to_timer_mode(void) { /* */ //AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC1] = PRIORITY_TIMER1 | AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_TC1] = PRIORITY_TIMER1 | AT91C_AIC_SRCTYPE_INT_EDGE_TRIGGERED;
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_TC1] = (unsigned int)ih_timer1_overload; /* ðàçðåøàåì ïðåðûâàíèå îò êàíàëà 1 òàéìåðà-ñ÷åò÷èêà */ AT91C_BASE_AIC->AIC_IECR = (1 << AT91C_ID_TC1);
/* ïîäêëþ÷àåì ê êàíàëó ñèñòåìíóþ ÷àñòîòó è âêëþ÷àåì âûâîä */ AT91F_PMC_EnablePeriphClock(AT91C_BASE_PMC, 1 << AT91C_ID_TC1);
/* */ AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO;
AT91C_BASE_TC1->TC_RC = 0xFFFF; AT91C_BASE_TC1->TC_IER = AT91C_TC_CPCS;
/* çàïóñêàåì òàéìåð */ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; } далее пишется простенький обработчик Код void ih_timer1_overload(void) __irq { // Time = AT91C_BASE_AIC->AIC_IVR; //automatic clear current interrupt AT91C_BASE_AIC->AIC_ICCR = (1 << AT91C_ID_TC1); //clear current interrupt //if(AT91C_BASE_TC1->TC_SR & AT91C_TC_CPCS) { Time = 0xFFFF; ReloadCountTime++; ReloadCountPulses = 0; } } Что не понятно. 1. Надо ли очищать какой-то флаг источника прерываний в САМе? То есть правильно ли я делаю что пишу первую(закоментированную) или вторую строчки обработчика? 2. Каким образом таймер генерит прерывания и выбирается их конкретный источник (сравнение по ra rb rc, захват и пр.) в даташите по этому поводу очень грамотно написано Цитата Interrupt The TC has an interrupt line connected to the Advanced Interrupt Controller (AIC). Handling the TC interrupt requires programming the AIC before configuring the TC. Круто ничего не скажешь... дальше то что? по поводу определения истьочника подозреваю надо читать статус. Но генерятся то прерывания когда? 3 Прерывание вызывается но только один раз. Подозреваю это из-за того что я что-то упустил с источниками прерываний. Или вообще что-то упустил. При этом я вижу в эмуляторе что флаг cpcs в регистре статуса не изменяется. При каких условиях сбрасывается CPCS? Памажите а?
--------------------
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.
|
|
|
|
|
Jun 26 2006, 10:36
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(SpiritDance @ Jun 26 2006, 13:41)  1. Надо ли очищать какой-то флаг источника прерываний в САМе? То есть правильно ли я делаю что пишу первую(закоментированную) или вторую строчки обработчика?
2. Каким образом таймер генерит прерывания и выбирается их конкретный источник (сравнение по ra rb rc, захват и пр.) в даташите по этому поводу очень грамотно написано
3 Прерывание вызывается но только один раз. Подозреваю это из-за того что я что-то упустил с источниками прерываний. Или вообще что-то упустил. При этом я вижу в эмуляторе что флаг cpcs в регистре статуса не изменяется. При каких условиях сбрасывается CPCS? 1. Нужно читать TC_SR. Раскомментируйте вторую строку и добавьте в конце AT91C_BASE_AIC->AIC_EOICR = 0x00; 2. Если активен один или несколько источников в таймере, то будет вызвано прерывание. 3. см. п.1 Документация у атмела совершенно нормальная, тщательнее надо
Сообщение отредактировал aaarrr - Jun 26 2006, 10:39
|
|
|
|
|
Jul 26 2006, 22:04
|

фанат Linux'а
    
Группа: Свой
Сообщений: 1 353
Регистрация: 23-10-05
Из: SPB.RU
Пользователь №: 10 008

|
Спасите, я тоже уже готов повеситься. Не могу понять как заставить срабатывать прерывание по RTT. Таймер запускается и считает ~1 раз в секунду, но самого прерывание не происходит... Возможно чего-нибудь очень важное забыл настроить... ЗЫ Отлаживаю на реальном sam7s64 через Wiggler в CW 1.6 Код int y = 0; void IntHandler() { y++; }
int main(void) { struct x a; int i; AIC_SVR12 = (int)IntHandler; AIC_SMR12 |= 1; RTT_VR = 0; RTT_MR = 0x00008000 | RTT_MR_RTTINCIEN | RTT_MR_RTTRST; AIC_IECR |= 1<<12; PMC_PCER = (1<<2); int w = 0; debug_printf("Initialized!\n"); while(1) { if(w != RTT_VR) { debug_printf("New value of RTT_VR = %4i; y = %4i\n", RTT_VR, y); w = RTT_VR; } } return 0; } Лог: Код Initialized! New value of RTT_VR = 1; y = 0 New value of RTT_VR = 2; y = 0 New value of RTT_VR = 3; y = 0
Сообщение отредактировал AVR - Jul 26 2006, 22:06
--------------------
|
|
|
|
|
Jul 27 2006, 06:57
|

Дух погибшего транзистора
   
Группа: Свой
Сообщений: 877
Регистрация: 6-09-05
Из: Москва
Пользователь №: 8 288

|
Какой-то не такой у вас файл описаний  , возьмите лучше это. На вскидку помарки в коде В прерывании не читается SR PIO включать не обязательно PMC_PCER = (1<<2); Регистр VR - read-only. на всякий случай volatile int y 12 соответсвует AT91C_ID_TC0, а RTT я что то вообще не нашел.
--------------------
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.
|
|
|
|
|
Jul 27 2006, 20:46
|

фанат Linux'а
    
Группа: Свой
Сообщений: 1 353
Регистрация: 23-10-05
Из: SPB.RU
Пользователь №: 10 008

|
SpiritDance, ничего не помогло... PeripheralID для RTT тоже не нашел... Приведите, пожалуйста, пример наипростейшей инициализации прерывания от таймера. ЗЫ К IAR конечно есть примеры, в которых это всё расписано, но в них я не вижу ничего принципиально отличного от того что у меня... =( ЗЫЗЫ Вот в AVRке достаточно SEI и просто записать битик разрешающий то или иное прерывание...
--------------------
|
|
|
|
|
Jul 28 2006, 06:08
|

Дух погибшего транзистора
   
Группа: Свой
Сообщений: 877
Регистрация: 6-09-05
Из: Москва
Пользователь №: 8 288

|
Цитата(AVR @ Jul 28 2006, 00:46)  SpiritDance, ничего не помогло...  И не должно было. ID то не тот. И AIC вы не на то прерывание инициализируете, и хендлер не туда записываете. Я только указал на то на что можно было еще наступить. aaarrr Очередное спасибо за то что несете свет в наше темное царство.
--------------------
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.
|
|
|
|
|
Jul 29 2006, 15:32
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(AVR @ Jul 29 2006, 14:29)  Не получается...  Во-первых, функция обработки прерывания должна иметь соответствующий модификатор - __irq, __interrupt и т.п., не знаю, что должно быть в CW. Далее, читать AIC_IVR не нужно, AIC_IECR - это write-only регистр, писать в AIC_ISCR ничего не нужно. Кроме того, Вы пишите AIC_SMR1 вместо AIC_SMR2. Теперь примеры кода. Номер 1, с level sensetive прерыванием. Здесь требуется дополнительная проверка в основном цикле, так как прерывание RTT снимается аж через 2 цикла SCLK после чтения статуса. Код void rtt_init(void) { *AT91C_RTTC_RTMR = 0x00008000 | AT91C_RTTC_RTTINCIEN | AT91C_RTTC_RTTRST;
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_SYS] = (u_int)rtt_handler; AT91C_BASE_AIC->AIC_IECR = (0x01 << AT91C_ID_SYS); }
void main(void) { while(0x01) { if((*AT91C_RTTC_RTSR & AT91C_RTTC_RTTINC) == 0x00) *AT91C_RTTC_RTMR |= AT91C_RTTC_RTTINCIEN;
... } }
__irq void rtt_handler(void) { u_int a;
a = *AT91C_RTTC_RTSR; y++; *AT91C_RTTC_RTMR &= ~AT91C_RTTC_RTTINCIEN; *AT91C_AIC_EOICR = a; } Номер 2, с edge sensetive прерыванием. Проще, но вылезут проблемы при использовании других источников для SYS_IRQ. Код void rtt_init(void) { *AT91C_RTTC_RTMR = 0x00008000 | AT91C_RTTC_RTTINCIEN | AT91C_RTTC_RTTRST;
AT91C_BASE_AIC->AIC_SVR[AT91C_ID_SYS] = (u_int)rtt_handler; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_SYS] = (0x01 << 0x05); AT91C_BASE_AIC->AIC_IECR = (0x01 << AT91C_ID_SYS); }
__irq void rtt_handler(void) { u_int a;
a = *AT91C_RTTC_RTSR; y++; *AT91C_AIC_EOICR = a; }
|
|
|
|
|
Aug 2 2006, 22:27
|

фанат Linux'а
    
Группа: Свой
Сообщений: 1 353
Регистрация: 23-10-05
Из: SPB.RU
Пользователь №: 10 008

|
Спасибо, aaarrr. Код #include "AT91SAM7S64.h" #include "system.h" typedef unsigned char byte; byte sw = 0;
__irq void IRQ_1() { unsigned int a; a = *AT91C_RTTC_RTSR; sw = !sw; if(sw) AT91C_BASE_PIOA->PIO_CODR = BIT30; else AT91C_BASE_PIOA->PIO_SODR = BIT30; AT91C_BASE_RTTC->RTTC_RTMR &= ~AT91C_RTTC_RTTINCIEN; AT91C_BASE_AIC->AIC_EOICR = a; }
int main() { AT91C_BASE_PMC->PMC_PCER = 1<<AT91C_ID_PIOA; AT91C_BASE_PIOA->PIO_PER |= BIT30; AT91C_BASE_PIOA->PIO_OER |= BIT30; AT91C_BASE_PIOA->PIO_CODR |= BIT30; AT91C_BASE_RTTC->RTTC_RTMR = 0x00008000 | AT91C_RTTC_RTTINCIEN | AT91C_RTTC_RTTRST; AT91C_BASE_AIC->AIC_SVR[AT91C_ID_SYS] = (unsigned int)IRQ_1; AT91C_BASE_AIC->AIC_SMR[AT91C_ID_SYS] = (0x01 << 0x05); AT91C_BASE_AIC->AIC_IECR = (0x01 << AT91C_ID_SYS); while(1); } Всё это запустил на sam7s64 через wiggler в iar. По-прежнему прерывание не происходит, хотя таймер тикает ~раз в секунду... Возможно ли что всё дело в самом sam7s64? Данный код я запускаю из RAM - может ли это повлиять на работоспособность блока прерываний?
--------------------
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|