реклама на сайте
подробности

 
 
> Проблема с прерываниями от таймера в AT91R40008, не срабатывает прерывание по достижению счетчиком заданного значения
Supernaut
сообщение Mar 15 2007, 16:15
Сообщение #1


Участник
*

Группа: Новичок
Сообщений: 31
Регистрация: 12-05-06
Пользователь №: 17 028



Привет всем!
Кто-нибудь сталкивался с такой трудностью - не срабатывает прерывание от таймера, хотя само событие, по которому должно случиться прерывание - происходит?
Таймер должен отмерять интервал времени 300 мкс для формирования манчестерского кода. Приведу кусок своей программы, может, кто-нибудь увидит ошибку:

Код
/* Настраиваем регистры контроллера прерываний */
  AIC_IECR = (unsigned int)(1<<TC0IRQ); // бит TC0IRQ = 1 - разреш. прер. от таймера (канал 0)
  AIC_SMR4 = 0x00000007;            // PRIOR   = 111  - приоритет =7 - самый высший
                                // SRCTYPE = 00   - по уровню
  AIC_SVR4 = (unsigned int)(&TC0_IRQ);  // адрес обработчика прерывания таймера (канал 0)

/* Настраиваем 0-й канал таймера */
  TC_BCR=0x00000000;   // SYNC=0 - 3 блока таймера работают независимо;
  TC_BMR=0x00000015;   // TC0XC0S=01 \
                  // TC0XC1S=01  | запрещ. внеш. такт. сигналы для всех 3-х блоков
                  // TC0XC2S=01 /

  TC_CCR0=0x00000001;  // CLKEN=1    - разрешаем подачу тактовой частоты на канал 0

  TC_CMR0=0x00008040;  // TCCLKS=000 - такт. частота MCK/2=32,768 МГц
                   // CLKI=0     - не инвертируем такт. частоту
                   // BURST=00   - такт. частота - не управляется внешним сигналом
                   // CPCSTOP=1  - останов такт. ч-ты когда достигнем значения RC0
                   // CPCDIS=0   - не запрещаем такт. ч-ту когда достигнем значения RC0
                   // EEVTEDG=00
                   // EEVT=00
                   // ENETRG=0
                   // CPCTRG=0
                   // WAVE=1     - waveform mode
                   // остальные биты=0 - никакой внешней реакции на достижение RC0

  TC_RC0 = T_300mks;              // константа, соотв. 300 мкс при такт. ч-те =32,768 МГц
  TC_IER0=(unsigned int)(1<<CPCS);  // CPCS=1 - прерывание по достижению значения RC0

/* Обработчик прерывания от таймера 300 мкс (канал 0). Для отладки - моргнуть светодиодом и записать некое число в регистр tmp */
__irq __arm void TC0_IRQ(void)
{
tmp = AIC_IVR;
tmp = 0xAABBCCDD;

PIO_SODR=1<<4;
delay(10);              // Задержка 10 мкс
PIO_CODR=1<<4;

AIC_EOICR = 1;
}

/* Основная программа */
.............................
/* Запускаем таймер и ждем пока пройдет 300 мкс */
  TC_CCR0=(TC_CCR0 | 0x00000004);     // SWTRG=1 - сброс таймера и подача такт. частоты      
            while(1)
            {
              if( ((TC_SR0 >> CPCS) & 1) == 1 ) break;
//              if( tmp == 0xAABBCCDD ) { tmp=0; break; }
            }
...........................


Если выхожу из бесконечного цикла по флагу CPCS в статусном регистре TC_SR0 - все в порядке, т. е. таймер работает правильно. Тем не менее, если заменить усл-е выхода из бесконечного цикла на закомментированное - программа не работает, т. е. обработчик прерывания не выполняется.

Буду очень благодарен за советы и за любую помощь.

Сообщение отредактировал Supernaut - Mar 15 2007, 16:17
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 7)
SpiritDance
сообщение Mar 15 2007, 18:39
Сообщение #2


Дух погибшего транзистора
****

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



А глобально прерывания резрешены? (в смысле в регистре cpsr)


--------------------
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.
Go to the top of the page
 
+Quote Post
Supernaut
сообщение Mar 16 2007, 09:47
Сообщение #3


Участник
*

Группа: Новичок
Сообщений: 31
Регистрация: 12-05-06
Пользователь №: 17 028



Цитата(SpiritDance @ Mar 15 2007, 21:39) *
А глобально прерывания резрешены? (в смысле в регистре cpsr)


Да, разрешены - бит I в регистре cpsr прописывается =0 еще в загрузчике. После всех предварительных настроек загрузчик передает управление основной программе, кусок которой я привел.
Go to the top of the page
 
+Quote Post
SpiritDance
сообщение Mar 16 2007, 10:22
Сообщение #4


Дух погибшего транзистора
****

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



А другие какие нибудь прерывания работают?

Пока из помарок увидел только
AIC_SVR4 = (unsigned int)(&TC0_IRQ);
Зачем & ? можно вполне без него обойтись
адрес то прерывания точно тот?
В обработчике статусный регистр почему не читаете? как определяете что break не проходит? Я бы на вашем месте светодиод после выхода из бесконечного цикла зажег.


--------------------
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.
Go to the top of the page
 
+Quote Post
Supernaut
сообщение Mar 16 2007, 12:01
Сообщение #5


Участник
*

Группа: Новичок
Сообщений: 31
Регистрация: 12-05-06
Пользователь №: 17 028



Цитата(SpiritDance @ Mar 16 2007, 13:22) *
А другие какие нибудь прерывания работают?


Работают внешние прерывания IRQ0, IRQ1, IRQ2 (источники 16, 17, 18 соответственно). Правда, не в моей программе, а в другой, которую я взял как образец. Настройки для AIC там аналогичные.

Цитата
Пока из помарок увидел только
AIC_SVR4 = (unsigned int)(&TC0_IRQ);
Зачем & ? можно вполне без него обойтись


Честно говоря, я не большой специалист в программировании на С. Если имя функции является указателем на ее место в памяти - тогда да, Вы правы.

Цитата
адрес то прерывания точно тот?


Да, тот. Источник прерывания №4 - это 0-вой канал таймера. Неоднократно всё уже сверял с даташитом.

Цитата
В обработчике статусный регистр почему не читаете? как определяете что break не проходит? Я бы на вашем месте светодиод после выхода из бесконечного цикла зажег.


Какой Вы имеете в виду статусный регистр - регистр таймера TC_SR0 или регистр контроллера прерываний AIC_ ISR? Если первый - то в этом нет смысла, т. к. в данном случае я знаю, что прерывание может произойти только по событию TC_CV=RC0. Если второе - зачем мне знать номер источника, вызвавшего прерывание, если я уже и так оказался в обработчике нужного прерывания? Может, я неверно рассуждаю, но, по крайней мере, в даташите я ничего не нашел про обязательное чтение статусного регистра.

Насчет break все просто - если я пытаюсь выйти из цикла по условию tmp=0xCCAAABBB (запись этого числа должна происходить в обработчике прерывания), то просто происходит сброс контроллера по сторожевому таймеру. tmp объявлена как глобальная переменная, т. е., по идее, видна и из обработчика прерывания, и из основной программы... да и компилятор бы ругался, если с этим что не так...

В общем, не знаю где копать...
Go to the top of the page
 
+Quote Post
SpiritDance
сообщение Mar 16 2007, 12:28
Сообщение #6


Дух погибшего транзистора
****

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



Цитата(Supernaut @ Mar 16 2007, 12:01) *
Да, тот. Источник прерывания №4 - это 0-вой канал таймера. Неоднократно всё уже сверял с даташитом.

А адрес в него заносистя именно той функции, и она присутствует в map-файле?

Цитата(Supernaut @ Mar 16 2007, 12:01) *
Какой Вы имеете в виду статусный регистр - регистр таймера TC_SR0 или регистр контроллера прерываний AIC_ ISR? Если первый - то в этом нет смысла, т. к. в данном случае я знаю, что прерывание может произойти только по событию TC_CV=RC0. Если второе - зачем мне знать номер источника, вызвавшего прерывание, если я уже и так оказался в обработчике нужного прерывания? Может, я неверно рассуждаю, но, по крайней мере, в даташите я ничего не нашел про обязательное чтение статусного регистра.

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

Что-то я ничего не понял про сторожевой таймер. Вы его нигде не сбрасываете, ни в том не в другом варианте. И если Вы его включаете контроллер в любом случае должен сбрасываться.

PS
Попробуйте сходить вот сюда
http://atmel.com/dyn/products/tools.asp?family_id=605
, взять софтовые примеры посмотреть на них, взить из примеров включаемые файлы и libxxx.h файл и сделать все через них. Потому как разбираться в непоименованных константах тяжело.


--------------------
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.
Go to the top of the page
 
+Quote Post
Supernaut
сообщение Mar 16 2007, 14:09
Сообщение #7


Участник
*

Группа: Новичок
Сообщений: 31
Регистрация: 12-05-06
Пользователь №: 17 028



Цитата(SpiritDance @ Mar 16 2007, 15:28) *
А адрес в него заносистя именно той функции, и она присутствует в map-файле?

Да, функция обработчика прерывания TC0_IRQ() упоминается в map файле, и именно ее адрес передается контроллеру прерываний: AIC_SVR4 = (unsigned int)(&TC0_IRQ).
Цитата
Я имею ввиду статусный регистр таймера читать его нужно чтобы очистить флаг прерывания, иначе оно будет вызыватся постоянно, возможно даже не завершившись.

Попробовал прочитать его в обработчике прерываний. Результат тот же sad.gif
Цитата
Что-то я ничего не понял про сторожевой таймер. Вы его нигде не сбрасываете, ни в том не в другом варианте. И если Вы его включаете контроллер в любом случае должен сбрасываться.

Я имел в виду, что выход из бесконечного цикла происходит не по окончании обработчика прерывания, а по срабатыванию сторожевого таймера - т. е. контроллер просто сбрасывается. Сброс же самого вачдога происходит непосредственно перед запуском таймера и входом в бесконечный цикл while(1).



Победа!!!
SpiritDance, Вы были правы!!! Действительно, надо было читать статусный регистр таймера в обработчике прерывания! Просто я купился на вот эту строчку в даташите:
The interrupt handler must read the AIC_IVR as soon as possible.
В общем, правильная функция обработчика прерывания выглядит так:
Код
__irq __arm void TC0_IRQ(void)
{
tmp = TC_SR0;
tmp = 0xAABBCCDD;

PIO_SODR=1<<4;
delay(10);              // Задержка 10 мкс
PIO_CODR=1<<4;

AIC_EOICR = 1;
}


Надеюсь, это кому-нибудь поможет.
SpiritDance, огромное спасибо за живое обсуждение!!!
Go to the top of the page
 
+Quote Post
SpiritDance
сообщение Mar 16 2007, 14:51
Сообщение #8


Дух погибшего транзистора
****

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



welcome wink.gif

Кстати такое чтение статусного регистра компилятор может заоптимизировать, от греха лучше сделать так:
Код
__irq __arm void TC0_IRQ(void)
{
tmp1 = TC_SR0;
tmp = 0xAABBCCDD;

PIO_SODR=1<<4;
delay(10);              // Задержка 10 мкс
PIO_CODR=1<<4;

AIC_EOICR = tmp1;
}

Ну или проанализировать все-таки флаг сравнения


--------------------
Yes, there are two paths you can go by But in the long run Theres still time to change the road youre on.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th July 2025 - 18:20
Рейтинг@Mail.ru


Страница сгенерированна за 0.01425 секунд с 7
ELECTRONIX ©2004-2016