|
|
  |
прерывания от таймеров в SAM, опять затупил :( |
|
|
|
Aug 5 2006, 23:13
|

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

|
Цитата(aaarrr @ Aug 6 2006, 02:56)  Что-то меня настораживает. Все же на 0x18 должно быть ldr pc, [pc, #-0xf20], или что-нибудь не столь лаконичное, но аналогичное по смыслу. А pragma vector = 0x18 - какая-то вредная штуковина, ИМХО. Не, всё на самом деле нормально, теперь по адресу 0x18 висит инструкция ldr pc, [pc, #+24] А использование pragma vector = 0x18 прописано в справке на iccarm для обработчиков прерываний.
--------------------
|
|
|
|
|
Aug 6 2006, 12:20
|

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

|
Цитата(aaarrr @ Aug 6 2006, 04:05)  P.S. Интересно, кто-нибудь еще использовал в своих проектах RTT? У меня ещё вопрос возник: почему atmel называет это риалтайм таймером, если к нему подается только источник SLCK, частота которого только приблизительно равна 32768 Гц. Часы на таком явно не организовать... Есть ли возможность настроить на другой источник тактов? ЗЫ Можно ли и как заставить SAM7S пропускать MCK на один из выходов PIO, чтобы, например, тактировать внешнюю периферию такую как CPLD? ЗЫЗЫ Посоветуйте, пожалуйста, какую-нибудь микросхему SRAM в DIP корпусе на 64 КБайт.
Сообщение отредактировал AVR - Aug 6 2006, 12:44
--------------------
|
|
|
|
|
Aug 6 2006, 13:53
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(AVR @ Aug 6 2006, 16:20)  Есть ли возможность настроить на другой источник тактов? Нет. Цитата(AVR @ Aug 6 2006, 16:20)  Можно ли и как заставить SAM7S пропускать MCK на один из выходов PIO, чтобы, например, тактировать внешнюю периферию такую как CPLD? Можно. Почитайте про Programmable Clock Output в PMC.
|
|
|
|
|
Aug 8 2006, 12:07
|

Гуру
     
Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095

|
Цитата(AVR @ Aug 8 2006, 14:57)  Что нужно сделать, чтобы срабатывали несколько разных перерываний? Ведь тогда получается разные обработчики должны начинаться на 0x18, а одновременно это невозможно... Для чего тогда нужен AIC, если он сам автоматом не загружает в PC адрес нужно обработчика...  Код __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;
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Aug 16 2006, 05:33
|
Частый гость
 
Группа: Участник
Сообщений: 119
Регистрация: 3-07-06
Пользователь №: 18 528

|
Прошу прощения, что поднимаю старую тему и за очередной глупый для Вашего внимания вопрос, но ... объясните мне пожалуйста, в чем причина? Использую таймер и он в обработчике виснет:
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 - Aug 16 2006, 05:35
|
|
|
|
|
Aug 16 2006, 20:14
|

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

|
Цитата(Timofey @ Aug 16 2006, 09:33)  Если закоментировать строку 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; }
--------------------
|
|
|
|
|
Aug 17 2006, 03:56
|
Частый гость
 
Группа: Участник
Сообщений: 119
Регистрация: 3-07-06
Пользователь №: 18 528

|
Цитата(AVR @ Aug 17 2006, 02:14)  По всей видимости, функция "channal" выполняется слишком долго (вообще помещать такие страшные функции в обработчики это не очень хорошо  ), попробуйте вынести её в основной цикл программы, а при срабатывании прерывания по таймеру просто инкрементируйте некую переменную, которая сообщит программе в основном цикле о том, что нужно вызвать channal (и при этом декрементируйте эту переменную). За код спасибо. На счет того что в прерывании лучше вобще ничего делать, я знаю, но дело в том что больше никак. Мне нужно все это делать именно в прерывании ... В этом то и фишка ...
|
|
|
|
|
Sep 11 2006, 11:07
|

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

|
Исходные данные Инициализация Код 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; } Других обработчиков от системного контроллера нет. Вопрос. Почему обработчик ни разу не вызывается? Что я не понимаю?
--------------------
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.
|
|
|
|
|
Sep 11 2006, 12:28
|

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

|
Кто-нибудь может скинуть рабочий код для PIT? Странно но заработало вот так (я там кстати включить прерывание забыл  ) Код 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?
--------------------
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|