|
Прерывания от одного источника становятся в очередь, если прерывание возникло во время работы обработчика?, at91sam7s |
|
|
|
Dec 11 2009, 09:32
|
Местный
  
Группа: Участник
Сообщений: 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, но прерывание занято, следовательно, бит данных пропадает. Такое может быть или же сучествует очередь для одинаковых прерываний?
Причина редактирования: Уменьшение видимого размера цитаты исходника.
|
|
|
|
|
 |
Ответов
|
Dec 11 2009, 10:40
|
Местный
  
Группа: Участник
Сообщений: 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?
Причина редактирования: Уменьшение видимого размера цитаты исходника.
|
|
|
|
|
Dec 11 2009, 11:07
|
Гуру
     
Группа: Свой
Сообщений: 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 в самое начало обработчика.
|
|
|
|
|
Dec 11 2009, 12:37
|
Местный
  
Группа: Участник
Сообщений: 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 единицы или одну?
Причина редактирования: Уменьшение видимого размера цитаты исходника.
|
|
|
|
Сообщений в этой теме
Bulat Прерывания от одного источника становятся в очередь, если прерывание возникло во время работы обработчика? Dec 11 2009, 09:32    defunct Цитата(Bulat @ Dec 11 2009, 14:37) volati... Dec 11 2009, 16:34 DpInRock По хорошему, надо сброс всех событий делать по вых... Dec 11 2009, 12:48 Bulat Цитата(DpInRock @ Dec 11 2009, 17:48) По ... Dec 11 2009, 13:06 DpInRock Прерывание - это лишь повод запустить обработчик. ... Dec 11 2009, 14:27 Bulat Цитата(DpInRock @ Dec 11 2009, 19:27) Пре... Dec 11 2009, 14:55 DpInRock Если внутри обработчика прерывания возникают событ... Dec 11 2009, 15:44 defunct Цитата(DpInRock @ Dec 11 2009, 17:44) Есл... Dec 11 2009, 16:56 DpInRock Потому что это регистры. Dec 11 2009, 16:50
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|