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

 
 
 
Reply to this topicStart new topic
> Прерывания от одного источника становятся в очередь, если прерывание возникло во время работы обработчика?, at91sam7s
Bulat
сообщение Dec 11 2009, 09:32
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Прерывания от порта PIO становятся в очередь, если прерывание возникло во время работы обработчика?
Обработчик:
CODE
__ramfunc void irq_Receive()
{
volatile unsigned int dummy;
volatile unsigned int source; //источник прерывания

source = regs->PIOA_PDSR&0x780; //Накладываем маску прерывания

switch(source)
{
case 0x200 : {PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG;
recA = recA>>1; i_shA++; recA = recA|0x80000000; break;} //A1
case 0x400 : {PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG;
recA = recA>>1; i_shA++; recA = recA&0x7FFFFFFF; break;} //B1

case 0x80 : {PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG;
recB = recB>>1; i_shB++; recB = recB|0x80000000; break;} //A2
case 0x100 : {PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG;
recB = recB>>1; i_shB++; recB = recB&0x7FFFFFFF; break;} //B2

case 0x280 : {PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG;
recA = recA>>1; i_shA++; recA = recA|0x80000000; PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN;
PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG; recB = recB>>1; i_shB++; recB = recB|0x80000000;
break;} //A1,A2
case 0x500 : {PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG;
recA = recA>>1; i_shA++; recA = recA&0x7FFFFFFF; PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN;
PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG; recB = recB>>1; i_shB++; recB = recB&0x7FFFFFFF;
break;} //B1,B2

case 0x300 : {PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG;
recA = recA>>1; i_shA++; recA = recA|0x80000000; PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN;
PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG; recB = recB>>1; i_shB++; recB = recB&0x7FFFFFFF;
break;} //A1,B2
case 0x480 : {PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG;
recB = recB>>1; i_shB++; recB = recB|0x80000000; PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN;
PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG; recA = recA>>1; i_shA++; recA = recA&0x7FFFFFFF;
break;} //A2,B1

default: {;}
}

dummy = AT91C_BASE_PIOA->PIO_ISR;
}


При изменении уровней порта PIO в соответствии с маской 0x780, возникает прерывание, которое обрабатывается обработчиком irq_Receive(). В зависимости от содержимого источника прерываний source в буфера recA и recB записывается 1 или 0 и происходит их сдвиг, а также запускаются таймеры 1 или 2, которые контролируют паузу между принимаемыми битами. То есть этот обработчик принимает данные от двух каналов. Когда данные поступают на порт PIO от 2-х каналов не одновременно, то возникают сбои при приеме данных и прнимаются не те данные. То есть, возможна ситуация, когда обработчик считывает данные в буфер канала А recA, а в этот момент приходит очередной импульс на порт PIO от канала B, но прерывание занято, следовательно, бит данных пропадает. Такое может быть или же сучествует очередь для одинаковых прерываний?
Причина редактирования: Уменьшение видимого размера цитаты исходника.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Dec 11 2009, 09:38
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Т.к. сброс прерывания PIO (чтение PIO_ISR) у вас выполняется в конце обработчика, то любое прерывание PIO, возникшее во время его выполнения, будет потеряно. Никаких очередей, естественно, нет.
Go to the top of the page
 
+Quote Post
Bulat
сообщение Dec 11 2009, 10:40
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата(aaarrr @ Dec 11 2009, 14:38) *
Т.к. сброс прерывания PIO (чтение PIO_ISR) у вас выполняется в конце обработчика, то любое прерывание PIO, возникшее во время его выполнения, будет потеряно. Никаких очередей, естественно, нет.


Вот вариант программы реализующей 4 обработчика от 4 источников прерывания: PA7,8,9,10.
CODE
__ramfunc void irq_Receive_7() //A2
{
volatile unsigned int dummy;

PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN;
PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG;
recB = recB>>1;
i_shB++;
recB = recB|0x80000000;

dummy = AT91C_BASE_PIOA->PIO_ISR;
}

__ramfunc void irq_Receive_8() //B2
{
volatile unsigned int dummy;

PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN;
PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG;
recB = recB>>1;
i_shB++;
recB = recB&0x7FFFFFFF;

dummy = AT91C_BASE_PIOA->PIO_ISR;
}

__ramfunc void irq_Receive_9() //A1
{
volatile unsigned int dummy;

PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN;
PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG;
recA = recA>>1;
i_shA++;
recA = recA|0x80000000;

dummy = AT91C_BASE_PIOA->PIO_ISR;
}

__ramfunc void irq_Receive_10() //B1
{
volatile unsigned int dummy;

PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN;
PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG;
recA = recA>>1;
i_shA++;
recA = recA&0x7FFFFFFF;

dummy = AT91C_BASE_PIOA->PIO_ISR;
}

//Настройка прерываний
void Receiver_ini()
{

AT91C_BASE_AIC->AIC_SVR[7] = (unsigned int)irq_Receive_7;
AT91C_BASE_AIC->AIC_SMR[7] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | PORT_INTERRUPT_LEVEL;
AT91C_BASE_AIC->AIC_IECR = (0x1 << 7);
AT91C_BASE_SYS->PIOA_IER = 7;

AT91C_BASE_AIC->AIC_SVR[8] = (unsigned int)irq_Receive_8;
AT91C_BASE_AIC->AIC_SMR[8] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | PORT_INTERRUPT_LEVEL;
AT91C_BASE_AIC->AIC_IECR = (0x1 << 8);
AT91C_BASE_SYS->PIOA_IER = 8;

AT91C_BASE_AIC->AIC_SVR[9] = (unsigned int)irq_Receive_9;
AT91C_BASE_AIC->AIC_SMR[9] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | PORT_INTERRUPT_LEVEL;
AT91C_BASE_AIC->AIC_IECR = (0x1 << 9);
AT91C_BASE_SYS->PIOA_IER = 9;

AT91C_BASE_AIC->AIC_SVR[10] = (unsigned int)irq_Receive_10;
AT91C_BASE_AIC->AIC_SMR[10] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | PORT_INTERRUPT_LEVEL;
AT91C_BASE_AIC->AIC_IECR = (0x1 << 10);
AT91C_BASE_SYS->PIOA_IER = 10;
}


Но так прерывания не работают. Как правильно настраивать прерывания от отдельных выводов PIO?
Причина редактирования: Уменьшение видимого размера цитаты исходника.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Dec 11 2009, 11:07
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Bulat @ Dec 11 2009, 13:40) *
Вот вариант программы реализующей 4 обработчика от 4 источников прерывания: PA7,8,9,10.
...
Но так прерывания не работают.

Естественно не работают. Какая связь между номерами линий PIO и номерами векторов AIC'а?

Цитата(Bulat @ Dec 11 2009, 13:40) *
Как правильно настраивать прерывания от отдельных выводов PIO?

PIO выдает одно прерывание для всех линий. Можно использовать выводы IRQx для получения дополнительных прерываний.
Попробуйте сначала перенести чтение PIO_ISR в самое начало обработчика.
Go to the top of the page
 
+Quote Post
Bulat
сообщение Dec 11 2009, 12:37
Сообщение #5


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата(aaarrr @ Dec 11 2009, 16:07) *
Можно использовать выводы IRQx для получения дополнительных прерываний.

Вы имеете в виду AT91C_ID_IRQ0 и AT91C_ID_IRQ1?
Цитата(aaarrr @ Dec 11 2009, 16:07) *
Попробуйте сначала перенести чтение PIO_ISR в самое начало обработчика.

Я переместил чтение PIO_ISR в начало обработчика. Я могу определять источник при чтении PIO_ISR? Просто у меня пока получается определять источник только при чтении регистра порта PDSR. В коде, приведенном ниже применяю логическое "И" между содержимым PIO_ISR и PIO_PDSR и по результату этой операции делаю switch. Таким образом, я хочу исключить лишнюю обработку при возникновении второго прерывания по спаду.
CODE
__ramfunc void irq_Receive()
{
volatile unsigned int dummy = AT91C_BASE_PIOA->PIO_ISR;
volatile unsigned int source = regs->PIOA_PDSR & 0x780; //источники прерываний - выводы PA7,8,9 или 10

dummy &= source;
switch(dummy)
{
case 0x200 : { PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG;
recA = recA>>1; i_shA++; recA = recA|0x80000000; break;} //A1
case 0x400 : {PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG;
recA = recA>>1; i_shA++; recA = recA&0x7FFFFFFF; break;} //B1

case 0x80 : {PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG;
recB = recB>>1; i_shB++; recB = recB|0x80000000; break;} //A2
case 0x100 : {PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG;
recB = recB>>1; i_shB++; recB = recB&0x7FFFFFFF; break;} //B2

case 0x280 : {PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG;
recA = recA>>1; i_shA++; recA = recA|0x80000000; PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN;
PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG; recB = recB>>1; i_shB++; recB = recB|0x80000000;
break;} //A1,A2
case 0x500 : {PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG;
recA = recA>>1; i_shA++; recA = recA&0x7FFFFFFF; PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN;
PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG; recB = recB>>1; i_shB++; recB = recB&0x7FFFFFFF;
break;} //B1,B2

case 0x300 : {PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG;
recA = recA>>1; i_shA++; recA = recA|0x80000000; PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN;
PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG; recB = recB>>1; i_shB++; recB = recB&0x7FFFFFFF;
break;} //A1,B2
case 0x480 : {PauseTimerBase2->TC_CCR = AT91C_TC_CLKEN; PauseTimerBase2->TC_CCR = AT91C_TC_SWTRG;
recB = recB>>1; i_shB++; recB = recB|0x80000000; PauseTimerBase1->TC_CCR = AT91C_TC_CLKEN;
PauseTimerBase1->TC_CCR = AT91C_TC_SWTRG; recA = recA>>1; i_shA++; recA = recA&0x7FFFFFFF;
break;} //A2,B1

}
}

//Настройка прерывания от PIO
void Receiver_ini()
{
unsigned int REC_MASK = 0x780;

AT91C_BASE_AIC->AIC_SVR[AT91C_ID_PIOA] = (unsigned int)irq_Receive;
AT91C_BASE_AIC->AIC_SMR[AT91C_ID_PIOA] = AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL | PORT_INTERRUPT_LEVEL;

AT91C_BASE_AIC->AIC_IECR = (0x1 << AT91C_ID_PIOA);
AT91C_BASE_SYS->PIOA_IER = REC_MASK;
}


Так можно делать? И еще возможен вариант одновременного возникновения единиц на 2-х выводах, в этом случае регистр PIO_ISR покажет 2 единицы или одну?
Причина редактирования: Уменьшение видимого размера цитаты исходника.
Go to the top of the page
 
+Quote Post
DpInRock
сообщение Dec 11 2009, 12:48
Сообщение #6


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



По хорошему, надо сброс всех событий делать по выходу из обработчика. А перед выходом проверять, не возникло ли какое событие, требующее этого обработчика ( и сответственно снова обработать оное). И так до тех пор пока событий не останется. После чего покидать обработчик.


--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
Bulat
сообщение Dec 11 2009, 13:06
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата(DpInRock @ Dec 11 2009, 17:48) *
По хорошему, надо сброс всех событий делать по выходу из обработчика. А перед выходом проверять, не возникло ли какое событие, требующее этого обработчика ( и сответственно снова обработать оное). И так до тех пор пока событий не останется. После чего покидать обработчик.

я сброс событий (чтение PIO_ISR) поставил в начале, чтобы поймать прерывание, пришедшее во время работы обработчика.
То есть, мне нужно повторно считывать PIO_ISR при выходе и в случае неравенства нулю его содержимого возвращаться в начало обработчика?
Go to the top of the page
 
+Quote Post
DpInRock
сообщение Dec 11 2009, 14:27
Сообщение #8


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



Прерывание - это лишь повод запустить обработчик. Смотрите на состояние информационных выводов. И после их успокоения сбрасывайте все флаги - и на выход.


--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
Bulat
сообщение Dec 11 2009, 14:55
Сообщение #9


Местный
***

Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241



Цитата(DpInRock @ Dec 11 2009, 19:27) *
Прерывание - это лишь повод запустить обработчик. Смотрите на состояние информационных выводов. И после их успокоения сбрасывайте все флаги - и на выход.

так данные на порт по каждому каналу идут с частотой 100 кГц, то есть при их неодновременном приходе на порт частота удваивается, а помимо прерывания от порта мне еще 2 прерывания надо обрабатывать, поэтому ждать "успокоения" я не могу.
Go to the top of the page
 
+Quote Post
DpInRock
сообщение Dec 11 2009, 15:44
Сообщение #10


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



Если внутри обработчика прерывания возникают события, которые должны обрабатываться этим же обработчиком, и нет паузы между этими событиями, то вы неверно спроектировали алгоритм или систему. (Т.е. обработчик в принципе не успевает обрабатывать).

Хотя лично я не вижу тут никаких проблем.


--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
defunct
сообщение Dec 11 2009, 16:34
Сообщение #11


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(Bulat @ Dec 11 2009, 14:37) *
volatile unsigned int dummy = AT91C_BASE_PIOA->PIO_ISR;
volatile unsigned int source = regs->PIOA_PDSR & 0x780;

говорите частота входного сигнала 100khz...

Вы можете обосновать зачем dummy и source объявлены у вас в обработчике как volatile?
Чтобы сделать обработчик более медленным?
Go to the top of the page
 
+Quote Post
DpInRock
сообщение Dec 11 2009, 16:50
Сообщение #12


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



Потому что это регистры.


--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
defunct
сообщение Dec 11 2009, 16:56
Сообщение #13


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(DpInRock @ Dec 11 2009, 17:44) *
Если внутри обработчика прерывания возникают события, которые должны обрабатываться этим же обработчиком, и нет паузы между этими событиями, то вы неверно спроектировали алгоритм или систему. (Т.е. обработчик в принципе не успевает обрабатывать).

Речь идет о pin-change 4-х source'ов. Допустим есть такие теоретические параметры:
- частота источника всегда одинакова и равна 1kHz (интервал между событиями 1000us).
- время выполнения обработчика для одного source в худшем случае равна 100us.

Для 4-х источников Система с четырьмя отдельными обработчиками, будет загружена всего на (4 * 100us / 1000us) * 100% = 40%.

Теперь переложим эту гипотетическую задачу на железо автора ветки. Проблема состоит в том, что здесь нет отдельных IRQ для каждого источника, а имеется один общий INT на все четыре события. События асинхронны - друг от друга не зависят. Соответвенно событие №4 может произойти как раз тогда когда обслуживается одно из событий 1-3.

Будут ли возникать события, которые должны обработаться тем же обработчиком - конечно будут (т.к. IRQ общий для всех событий, а события асинхронны).
Можно ли при этом говорить, что система спроетирована неверно?


Цитата
Потому что это регистры.

Вы Редькина начитались? Какие еще регистры. Я говорю о переменных dummy и status.
Go to the top of the page
 
+Quote Post

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

 


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


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