Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Проблема LPC2214 UART+T0 IRQ
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
dmyl
Прерывания два УАРТ и Таймер0, Т0 запускается периодически (отсчет таймаута), пока был один Т0 все работало, с делал прерывание на прием по УАРТу - какие-то глюки
Не получается разобраться в чем проблема, вот код
Инициализания прирываний:

static void DefDummyInterrupt(void)
{}

// IRQ exception handler. Calls the interrupt handlers.
#pragma vector=0x18
__irq __ramfunc void irq_handler(void)
{
void (*interrupt_function)();
unsigned long vector;

vector = VICVectAddr; // Get interrupt vector.
interrupt_function = (void(*)())vector;
// __enable_interrupt(); // Enable interrupts.
(*interrupt_function)(); // Call vectored interrupt function.

VICVectAddr = 0; // Clear interrupt in VIC.
}

//************************************************************
void init_IRQ(void)
{
// Setup interrupt controller.
VICProtection = 0;
// Disable all interrupts
VICIntEnClear = 0xffffffff;
VICDefVectAddr = (unsigned long)&DefDummyInterrupt;

// Setup timer callback function.
VICIntSelect=0x0; // Timer0 & UART select as IRQ.
VICVectAddr0 = (unsigned long)&UART0Interrupt;
VICVectCntl0 = 0x20 | VIC_UART0; // Enable vector interrupt for UART0.
VICVectAddr1 = (unsigned long)&Timer0Interrupt;
VICVectCntl1 = 0x20 | VIC_TIMER0; // Enable vector interrupt for timer 0.
VICIntEnable = 0x50; // Enable timer 0 & UART0 interrupt.
}

УАРТ - слот0
Т0- слот1
Процедура обработки для Т0 и УАРТа

// Timer0 interrupt handler
__ramfunc void Timer0Interrupt(void)
{
T0IR = 0xff; // Clear timer 0 interrupt line.
BF=0;
}

//******************************************************************
// Заполняет буфер приема
__ramfunc void UART0Interrupt()
{
while (U0LSR&0x1)
{
rx_buff[rx_end]=U0RBR;
rx_end=(rx_end+1)%RX_BUFF_LEN;
rx_len++;
}
}


Под житагом запускаю программу, передаю пакет данных. На него должен быть ответ, ответа нет. Останавливаю программу, пакет в буфер принимается верно, лишнего нет почему-то постоянно вылетает на DummyInterrupt, пока не тормознешь отладчиком ответа нет, после остановки отладчиком и снова запуска ответ передается.
Если точка останова на irq_handler то постоянно вылезают DummyInterrupt.
Вообщем чушь какая-то, отладить не получается стоит тормознуть отладчиком идут ответы на пакет.

Может есть пример рабочего кода для обработки приема по УАРТ?
dmyl
Немного переделал - выкинул Т0, оставил только прием по прерыванию. Передача в цикле по опросу заполнения буфера.
Такое впечатление что при возникновении прерывания в нем все и зацикливается.
Alex03
Цитата(dmyl @ Nov 22 2006, 14:11) *
Немного переделал - выкинул Т0, оставил только прием по прерыванию. Передача в цикле по опросу заполнения буфера.
Такое впечатление что при возникновении прерывания в нем все и зацикливается.


А почемуб по честному не читать IRR и в соответствии с причиной прерывания действовать, дабы это прерывание сбрасывалось.
amw
Использую оба указанных прерывания. Никаких проблем.
Вот пример обработчика:
Код
void uart0_interrupt(void)
{
    unsigned int iir;
    unsigned int data;
    
    if (on_uart0_int != NULL)
        on_uart0_int();
    else
    {
        iir = UART[0]->IIR;
        switch ((iir >> 1) & 0x07) {
            /* Receive line status interrupt */
            case 3:
                data = UART[0]->LSR;
                break;
                /* Receive data available interrupt */
            case 2:
                /* Character timeout indicator interrupt */
            case 6:
                data = UART[0]->RBR;
                break;
                /* Transmit holding register empty interrupt */
            case 1:
                break;
        }
    }
}

Вставте в case нужный код.
zltigo
Цитата(Alex03 @ Nov 22 2006, 13:32) *
А почемуб по честному не читать IRR и в соответствии с причиной прерывания действовать, дабы это прерывание сбрасывалось.

Это не честнее, это просто еще более громоздко. Нормальный подход это ОДНА команда:

Код
                ldr     pc,[pc,#-0xFF0]        ; 18 Jump directly to the address given by the AIC
                                               ; from [0xFFFFF020] Curent 18h +8(conveyer)=20h
Andrew2000
Цитата(dmyl @ Nov 22 2006, 11:44) *
Прерывания два УАРТ и Таймер0, Т0 запускается периодически (отсчет таймаута), пока был один Т0 все работало, с делал прерывание на прием по УАРТу - какие-то глюки....

Та же фигня, на LPC2129, компилил Rowley1.6b3 и Keil RVCT 3.0[B 947]
Через какое-то время перестают вызываться обработчики прерываний, хотя прерывания разрешены и в VIC и глобально. Ну не вызывается обработчик и все... (основной код крутиться).
Скорость "зависания" зависит от интенсивности обмена через UART.
Разница между этими версиями - код от Rowley "сваливается" через 5 сек, а от RVCT может несколько минут продержаться.

Spurious Int? Но, вроде, по инструкции делал ....
aaarrr
Цитата(Andrew2000 @ Nov 23 2006, 02:29) *
Та же фигня, на LPC2129, компилил Rowley1.6b3 и Keil RVCT 3.0[B 947]
Через какое-то время перестают вызываться обработчики прерываний, хотя прерывания разрешены и в VIC и глобально. Ну не вызывается обработчик и все... (основной код крутиться).
Скорость "зависания" зависит от интенсивности обмена через UART.

... Но, вроде, по инструкции делал ....

К инструкциям относится также и errat'а. Раздел Missed Interrupt Potential.
zltigo
Цитата(aaarrr @ Nov 23 2006, 03:22) *
К инструкциям относится также и errat'а. Раздел Missed Interrupt Potential.

Errata дело конечно такое :-(, но валить все, что в голову пришло на чужую голову явно не стоит.
Использование таймерого (без PWM/Capture наворотов), UART(115K на полной скорости), SPI, ADC, всех 4х внешних - и никаких проблем, кроме, конечно , описанной в Erratа процедуры инициализации.
Моя статистика наблюдений за "проблемами с прерываниями" на данном форуме, показывает, что в большинстве случаев они оказываются "проблемаим со стеком".
aaarrr
Цитата(zltigo @ Nov 23 2006, 10:20) *
Моя статистика наблюдений за "проблемами с прерываниями" на данном форуме, показывает, что в большинстве случаев они оказываются "проблемаим со стеком".

По-моему, описанная проблема - не вызывается обработчик прерывания - очень плохо вяжется с "проблемами со стеком".
dmyl
Проблему поборол, не понятно почему вычитывание данных UART до опустошения буфера (бит DR) не эквивалентно вычитыванию UART пока не снимется IIR. Прерывания УАРТа кроме RDA все запрещены.

Загадкой осталось такое поведение под отладчиком через JTAG.
Причем абсолютно точно, если висит окно просмотра регистров UART то прерывание сразу сбрасывалось, если окно закрыть то нет. Видимо чтение регистров сбрасывающих прерывания через JTAG в отладчике эквивалентно их чтению в программе. Вот и получается глюкодром.
zltigo
Цитата(dmyl @ Nov 23 2006, 15:40) *
Проблему поборол, не понятно почему вычитывание данных UART до опустошения буфера (бит DR) не эквивалентно вычитыванию UART пока не снимется IIR.

Странный подход к делу - НЕ должно оно сниматся от того, что буфер опустошили а должно только после того, как Вы дали понять, что на него среагировали, а уж какяя там Ваша реакция должна быть -
читать буфер, не читать буфер, читать, но в следующий понедельник - не его дело.

Цитата
Загадкой осталось такое поведение под отладчиком через JTAG.
Причем абсолютно точно, если висит окно просмотра регистров UART то прерывание сразу сбрасывалось, если окно закрыть то нет.

Какая "загадка" - висит отладчик и ЧИТАЕТ UART. Железу UART по барабану, кто его считал и дал знак,
что СРЕАГИРОВАЛ на прерывание.
dmyl
Цитата
Странный подход к делу - НЕ должно оно сниматся от того, что буфер опустошили а должно только после того, как Вы дали понять, что на него среагировали, а уж какяя там Ваша реакция должна быть -
читать буфер, не читать буфер, читать, но в следующий понедельник - не его дело.

Что же тут странного? Или есть другой способ дать понять что среагировали на прерывание по приему УАРТа и сбросить его кроме как прочитать данные из RBR?
bombastic
Цитата(dmyl @ Nov 22 2006, 11:44) *
Если точка останова на irq_handler то постоянно вылезают DummyInterrupt.

У меня такая же фигня, это наверно то что описано в SPURIOUS INTERRUPTS blink.gif
Не знаю пока каг с этим быть, я сейчас просто в VicDefVectAddr ничего не записываю...
А вобще VicDefVectAddr используется для обработки невекторированных прерываний,
если у тя все прерывания векторированые то VicDefVectAddr не нужно использовать.
zltigo
Цитата(dmyl @ Nov 24 2006, 09:22) *
Или есть другой способ дать понять что среагировали на прерывание по приему УАРТа и сбросить его кроме как прочитать данные из RBR?

Уж не знаю, как и обьяснить... Вы с железом когда нибудь до этого случая дело имели?
Контроллер прерывания и контроллер UART две РАЗНЫЕ вещи. Сброс источника прерывания в UART не является сигналом для снятия прерывания КОНТРОЛЛЕРОМ и наоборот. И это правильно(см. предыщее письмо)
dmyl
Цитата
Уж не знаю, как и обьяснить... Вы с железом когда нибудь до этого случая дело имели?

Уважаемый, я бы попросил.....
Цитата
Контроллер прерывания и контроллер UART две РАЗНЫЕ вещи. Сброс источника прерывания в UART не является сигналом для снятия прерывания КОНТРОЛЛЕРОМ и наоборот. И это правильно(см. предыщее письмо)

Если вы всетаки взгляните на код в начале ветки, то увидите что прерывание на контроллере сбрасывалось, а сброс источника прерывания на УАРТ выполнялся вычитываением буфера. Сбрасывая прерывание в VIC но не сбрасывая источник этого прерывания в контроллере УАРТа, вы его тутже получаете по новой, что я и имел удовольсвие наблюдать.
Поэтому вопрос как оказалось был в следующем (забудьте о VIC я про него и не спрашивал):
Почему сброс ИСТОЧНИКА прерывания по приему УАРТ путем чтения буфера по признаку DR и по признаку пока не снимется IIR не эквивалентны.
Сергей Борщ
Цитата(bombastic @ Nov 24 2006, 13:56) *
Цитата(dmyl @ Nov 22 2006, 11:44) *

Если точка останова на irq_handler то постоянно вылезают DummyInterrupt.

У меня такая же фигня, это наверно то что описано в SPURIOUS INTERRUPTS blink.gif
Попробуйте в окне регистров выбрать что-нибудь отличное от VIC. Или в .ddf уберите из описания этого окна VicVectAddr. Дело в том что чтение этого регистра (отладчиком) дает сигнал к загрузке в него след. значения.
zltigo
Цитата(dmyl @ Nov 24 2006, 14:55) *
Если вы всетаки взгляните на код в начале ветки, то увидите что прерывание на контроллере сбрасывалось

Виноват :-(, хотя лишнего там много, отформатировать не сочли нужным и код с разными 0x01 вместо поименованных констант тоже не способствует желанию читать.
Посмотрел. Все вышесказанное относится и к парочке IIR RBR. Вычитывание FIFO c отражением сего факта в LSR
не должно приводить с сбросу запроса прерывания равно как и сброс прерывания не должен приводить :-) к сбросу содержимого FIFO
Для полного счастья нужно и вычитать FIFO и считать IIR. Операции отдельные ибо я имею право читать FIFO когда и где мне заблагорассудится и это не должно приводить к "ичезновению" флага причины прерывния в IIR наоборот - считать IIR и решив, что мне сейчас не до этого - уйти не вычитывая FIFO.

Сие абослютно логично и описано в документации.
dmyl
Цитата(zltigo @ Nov 24 2006, 18:18) *
Для полного счастья нужно и вычитать FIFO и считать IIR.
....
Сие абослютно логично и описано в документации.

Простите, но смотрю в таблицу #81 UART0 Interrupt Handling мануала по 2214, нахожу нужные мне две строчки для IIR=0100 и 1100 (данные доступны и таймаут по приему), смотрю на заветную колонку INTERRUPT RESET, там черным по англицки написано U0RBR READ, и ни слова что нужно читать IIR. А выходит что не читая IIR а обходясь только LSR и RBR прерывание не сбрасывается, в докции в самом начале описания обработки прерывания прямо в тексте мелким шрифтом есть что-то похожее на то что надо IIR всеже надо прочитать до выхода из обработчика.

А насчет дефайнов - сорри, я код причесывал специально чтобы поменьше в ветку вываливать текста, кроме того я тег не поставил чтобы форматироание сохранилось smile.gif все время забываю какой он.
zltigo
Цитата(dmyl @ Nov 24 2006, 19:26) *
...там черным по англицки написано U0RBR READ, и ни слова что нужно читать IIR.
А выходит что не читая IIR а обходясь только LSR и RBR прерывание не сбрасывается,
в докции в самом начале описания обработки прерывания прямо в тексте мелким шрифтом есть что-то похожее на то что надо IIR всеже надо прочитать до выхода из обработчика.

Да нормальный там шрифт :-) и написано вполне "в лоб":
Код
Interrupts are handled as described in Table 9–105. Given the status of U0IIR[3:0], an
interrupt handler routine can determine the cause of the interrupt and how to clear the
active interrupt. The U0IIR must be read in order to clear the interrupt prior to exiting the
Interrupt Service Routine.

Ну а самое главное, к чему я собственно "привязался" это то, что такое поведение является правильным, логичным и привычным для железок которые позволяют реализовывать идеи "посложнее".

Еще результаты чтения:
Выкинуть промежуточный/первичный обработчик прерывания за полной его ненадобностью.
Ну и размещения кода в RAM не слишком уж ускоряет - MAM у LPC неплохой, зато чрезмерное увлечение подпрограммами уж точно тормозит.



Цитата(aaarrr @ Nov 23 2006, 11:46) *
По-моему, описанная проблема - не вызывается обработчик прерывания - очень плохо вяжется с "проблемами со стеком".

Прочитайте - там не "не вызывается" там:
Цитата
Через какое-то время перестают вызываться обработчики прерываний,

И я говорил о статистике, голой статистике - ввиду отсутствия информации к размышлению.
dmyl
Цитата(zltigo @ Nov 24 2006, 22:33) *
Еще результаты чтения:
Выкинуть промежуточный/первичный обработчик прерывания за полной его ненадобностью.

Это понятно, но ресурсов хватает выше крыши, а так СИ код прозрачен и понятен, врубать же ассемблерные куски лишние хлопоты. Я когда то давно спрашивал как это можно изящно изобразить на СИ, других вариантов не подсказали.
zltigo
Цитата(dmyl @ Nov 25 2006, 09:23) *
Это понятно, но ресурсов хватает выше крыши, а так СИ код прозрачен и понятен, врубать же ассемблерные куски лишние хлопоты.

A Вы свой cstartup.s79 тоже для ясности на "C" :-). Так вот - замените там одну "непонятную" строчку на другую и все.
Цитата
Я когда то давно спрашивал как это можно изящно изобразить на СИ, других вариантов не подсказали.

Даже на "C" изящность уж приведенный в первом посте код не тянет уж совсем :-(. Не говоря уже о соревновании в изяществе с ОДНОЙ строчкой на ASM.
dmyl
Цитата(zltigo @ Nov 25 2006, 12:58) *
Так вот - замените там одну "непонятную" строчку на другую и все.

А как выковырнуть из проекта "свой" стартап?
Со стартапом из ../lib естественно не прокатывает, там не стартап а сплошной комментарий.
zltigo
Цитата(dmyl @ Nov 25 2006, 13:03) *
Со стартапом из ../lib естественно не прокатывает, там не стартап а сплошной комментарий.

Не "выковырнуть" а положить свой, сделанный, из того-же самого библиотечного. Благо комментариев там много :-).
Если "мало" - в приложении моя болванка. Посеченная до почти полного минимализма - самое то для начала.
dmyl
Цитата(zltigo @ Nov 25 2006, 16:57) *
Если "мало" - в приложении моя болванка. Посеченная до почти полного минимализма - самое то для начала.

В каком приложении?
zltigo
Цитата(dmyl @ Nov 25 2006, 17:02) *
В каком приложении?

Отвлекся :-(. Добавлено.
Alex03
Цитата(zltigo @ Nov 22 2006, 20:39) *
Цитата(Alex03 @ Nov 22 2006, 13:32) *

А почемуб по честному не читать IRR и в соответствии с причиной прерывания действовать, дабы это прерывание сбрасывалось.

Это не честнее, это просто еще более громоздко. Нормальный подход это ОДНА команда:

Код
                ldr     pc,[pc,#-0xFF0]    ; 18 Jump directly to the address given by the AIC
                                              ; from [0xFFFFF020] Curent 18h +8(conveyer)=20h



А всётаки IRR в обработчике прерывания UART читать надо smile.gif
А если прерывания все кроме приёма отключены, это не значит что не надо обрабатывать другие ситуации типа RX Line status Error, что кстати тоже зачастую лучше далать в прерывании.

Ну а про общий обработчик IRQ прерывания, тут уж что кому нравится
Стартап CW автоматом генерит
Код
ldr     pc,[pc,#-0xFF0]

если определён VECTORED_IRQ_INTERRUPTS (и я этим пользуюсь).
Но тут надо помнить что запись в VICVectAddr нужна в каждом обработчике.

Но и общий обработчик IRQ в ряде случаев полезен, например в ОС-ах и т.д., проблема у автора треда не в нём была. smile.gif
zltigo
Цитата(Alex03 @ Nov 27 2006, 09:07) *
А всётаки IRR в обработчике прерывания UART читать надо smile.gif

Я утверждал обратное про обработчик прерывания UART а не про общий обработчик???
Цитата
А если прерывания все кроме приёма отключены, это не значит что не надо обрабатывать другие ситуации типа RX Line status Error, что кстати тоже зачастую лучше далать в прерывании.

А вот если 'отключены', то в IIR (полагаю речь идет о нем а не о каком-то IRR) их не будет и быть не
может.
Цитата
Но тут надо помнить что запись в VICVectAddr нужна в каждом обработчике.

Жуткий напряг и нагрузка на память программиста :-)
Цитата
Но и общий обработчик IRQ в ряде случаев полезен, например в ОС-ах и т.д.,

А вот с этого места, пожалуйста поподробнее. Очень люблю про OSы думать. Заинтриговали.
Цитата
проблема у автора треда не в нём была. smile.gif

А я сие и не утверждал - речь была просто о уменьшении количества выставленного на обозрение кода.
Alex03
Цитата(zltigo @ Nov 27 2006, 13:39) *
Цитата

Но и общий обработчик IRQ в ряде случаев полезен, например в ОС-ах и т.д.,

А вот с этого места, пожалуйста поподробнее. Очень люблю про OSы думать. Заинтриговали.


Если Вам надо выполнять одно и то-же действие перед и/или после любого из прерываний.
Например:
- Подсчёт статистики, такой как кол-во прерываний, систем_тайм/юзер_тайм и т.д.
- Переключение задач по соответствующим условиям, как то с низкоприоритетной прерванной задачи, на более (сильно/реалтайм) приоритетную, которая была выведена из спячки текущим прерыванием.
- Разрешение вложенных прерываний, опять же в соответствии с заданной в ОС логикой.

Также в ОС-ах бывает вызов нескольких зерегестрированных обработчиков по списку, как пример, в PC архитектуре когда на одном физическом прерывании может несколько девайсов висеть, и когда драйвера, а с ними и обработчики прерываний, являются динамически загружаемыми/выгружаемыми модулями.

Ну и как доп. уровень абстракции когда писатель драйвера конкретной железки, не занимается программированием MMU или там контроллера прерываний (как то запись в VICVectAddr smile.gif ), а использует допустимые (документированные) для данной ОС механизмы.

и т.д. зависит от ОС, от архитектуры и прочего.
Чем навороченнее ОС тем больше вариантов.
Я ОС-ем пока не писал. smile.gif
zltigo
Цитата(Alex03 @ Nov 27 2006, 14:26) *
Если Вам надо выполнять одно и то-же действие перед и/или после любого из прерываний.

Хорошо, посмотрим, что предлагается:
Цитата
- Подсчёт статистики, такой как кол-во прерываний,

Сильно. Просто общее количество прерываний и за каждое обработанное прерывание брать денюжку :-), хотя опять некоторые сложно обрабатывать а некоторве попроще. Тогда надо считать их отдельно, тогда зачем общий обработчик?
Цитата
систем_тайм/юзер_тайм и т.д.

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

Действия понятны, но с этим разбирается система а не какой-то универсальный пролог/эпилог ко всем прерываниям.
Цитата
- Разрешение вложенных прерываний, опять же в соответствии с заданной в ОС логикой.

Разрешение вложенных прерываний огульно любого в любом. Выделение, например стека, неведомого размера (или наоборот не выделение) под вложенное. Причем до того, когда когда управление
получит обработчик конкретного прерывания или таже OS. При этом не запущенный обработчик
прерывания той-же OS как-то "задает логику"? Вот когда он получит управление он и будет "задавать логику" и именно он а не прокладка перед ним.
Цитата
в PC архитектуре когда на одном физическом прерывании может несколько девайсов висеть

Это к архитектуре никакого отнощения не имеет, у меня вот прямо сейчас перед носом 16 на одном
прерывании висят. И разбирается кто вылез обработчик конкретного прерывания, который знает
как разобраться "кто сказал Гав" а не некая абстрактная прокладка для всех прерываний вместе взятых.
Цитата
и когда драйвера, а с ними и обработчики прерываний, являются динамически загружаемыми/выгружаемыми модулями.

Сильно. Т.е. девайса нет (не вставили), драйвера нет(не загрузили) а обработчик прерывания - вот он уже есть и готов работать с неведомым ему железом на неведомом прерывании.
Цитата
Ну и как доп. уровень абстракции когда писатель драйвера конкретной железки, не занимается программированием MMU или там контроллера прерываний (как то запись в VICVectAddr smile.gif ), а использует допустимые (документированные) для данной ОС механизмы.

Живые примеры вышеописанного "ненавязчивого сервиса" имеют место быть, только зачем для этого обязательно иметь некую абстрактную прокладку перед или после собственно обработчика прерывания, который будет писать писатель драйвера?
Цитата
Чем навороченнее ОС тем больше вариантов.

Навернуть можно много чего, вопрос зачем?
Конкретный пример наворота присутствовал в первом примере с которого топик начался. Наворот виден и кушает такты. Польза от наворота? Не писать в каждом обработчике в VICVectAddr? А если я, простите
захочу разрешить в одном (только упаси боже не во всех зараз) обработчике вложенные прерывания?
Нафига мне тогда такой сервис?
Alex03
Уважаемый zltigo!
У меня нет желания спорить с Вами.
Я лишь привёл несколько примеров, причём далеко на всех.

Цитата(zltigo @ Nov 27 2006, 21:23) *
Цитата(Alex03 @ Nov 27 2006, 14:26) *

- Подсчёт статистики, такой как кол-во прерываний,

Сильно. Просто общее количество прерываний и за каждое обработанное прерывание брать денюжку :-), хотя опять некоторые сложно обрабатывать а некоторве попроще. Тогда надо считать их отдельно, тогда зачем общий обработчик?


Ну почему же общее, считать по конкретному прерыванию.
Общий обработчик конечно же должен знать, скажем так, индекс прерывания.
Например в нашей ОС возможно максимум N источников прерываний.
Тогда имея
nIntCounts[N] - массив счётчиков по всем перрываниям
pIntFn[N] - массив указателей на зарегистрированные обработчики
В общем обработчике можно например так:
Код
    nIntCounts[nIntIdx]++;
    if(pIntFn[nIntIdx])
        pIntFn[nIntIdx]();

Откуда взять индекс? Зависит от архитектуры, но на примере того же LPC - а кто Вам сказал что в VicVectAddr/VicVectAddrX должен лежать именно адрес? Туда можно этот индекс и положить. smile.gif

Наберите в Linux-е командочку
Код
# cat /proc/interrupts

Притом если процев/ядер в системе несколько, то прерывания ещё и по каждому процу отдельно считаются.

Цитата
Цитата

систем_тайм/юзер_тайм и т.д.

А это уже конкретные обработчики, ну право-же не считать-же системное время по сумме прерываний от таймера, мышки и клавиатуры.

Не по сумме прерываний, а по сумме времени затраченного на исполнение прерываний, процессов ядра и юзерских процессов.
В роли таймера тут могут быть как некий системный таймер, так и какойнить счётчик тактов который например присутствует во всех современных пнях (и прочих x86).


Цитата
Цитата

- Переключение задач по соответствующим условиям, как то с низкоприоритетной прерванной задачи, на более (сильно/реалтайм) приоритетную, которая была выведена из спячки текущим прерыванием.

Действия понятны, но с этим разбирается система а не какой-то универсальный пролог/эпилог ко всем прерываниям.


И где по Вашему этим система разбирается?
1. Исполняется юзер-процесс
2. Происходит прерывание
3. Исполняется Ваш обработчик, который выводит из спячки высокоприоритетный процесс.
4. Возврат из прерывания
5. ??? Опять юзер-процесс ??? Где переключение контекста на высокоприоритетный процесс?

Цитата
Цитата

- Разрешение вложенных прерываний, опять же в соответствии с заданной в ОС логикой.

Разрешение вложенных прерываний огульно любого в любом. Выделение, например стека, неведомого размера (или наоборот не выделение) под вложенное. Причем до того, когда когда управление
получит обработчик конкретного прерывания или таже OS. При этом не запущенный обработчик
прерывания той-же OS как-то "задает логику"? Вот когда он получит управление он и будет "задавать логику" и именно он а не прокладка перед ним.


Ну почему же любого в любом?
Рядом с упомянутыми массивами nIntCounts[N], pIntFn[N] положите ещё массив с флагами для каждого прерывания, такими как возможность разрешения вложенности, флаг реентерабельности (повторного вхождения) и т.д.

Вариантов всегда множество.

В том же линуксе есть такое понятие bottom half.
При этом логику работы прерывания разбивают на две части
1. то что обязательно должно исполниться в обработчике прерывания.
2. то что обязанно исполниться после обработчика прерывания (например обработка данных), но до любого юзеского кода. Т.е. после прерывания исполняется системный процесс, который может быть в том числе прерван прерываниями.

Цитата
Цитата

в PC архитектуре когда на одном физическом прерывании может несколько девайсов висеть

Это к архитектуре никакого отнощения не имеет, у меня вот прямо сейчас перед носом 16 на одном
прерывании висят. И разбирается кто вылез обработчик конкретного прерывания, который знает
как разобраться "кто сказал Гав" а не некая абстрактная прокладка для всех прерываний вместе взятых.


Давайте видеть всю фразу, а не её части. PC архитектуру я приводил как пример, и то что Вы умеете разрулить "кто сказал Гав" заложенно в Вашей железячно-програмной архитектуре. Возвращаясь же к PC архитектуре там в случае нескольких девайсов на одной линии прерывания однозначно определить источник не возможно, и приходится ОС (точнее её универсальному обработчику прерывания) вызывать по очереди все зерегистрированные для данной линии обработчики, а уже конкретный обработчик первым делом проверяет своё железо на факт наличия прерывания, и именно по этому не советуют иметь несколько девайсов, особенно скоростных на одной линии прерывания.


Цитата
Цитата

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

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


Если Вы про универсальный обработчик - то да! Он может быть, но в нём нет кода по работе с неведомым железом, в нём есть код по вызову (или не вызову) зарегистрированного(ых) обработчика(ов). А регистрируют эти обработчики например драйвера при их загрузке и после инициализации железа.
И если вдруг произойдёт прерывание от некоего девайса для которого не зарегистрирован обработчик - то это факт наличия какихто неполадок в железе или ПО, который можно както обработать.


Цитата
Цитата

Ну и как доп. уровень абстракции когда писатель драйвера конкретной железки, не занимается программированием MMU или там контроллера прерываний (как то запись в VICVectAddr smile.gif ), а использует допустимые (документированные) для данной ОС механизмы.

Живые примеры вышеописанного "ненавязчивого сервиса" имеют место быть, только зачем для этого обязательно иметь некую абстрактную прокладку перед или после собственно обработчика прерывания, который будет писать писатель драйвера?


Про обязательность везде и всего я не говорил. smile.gif


Цитата
Цитата

Чем навороченнее ОС тем больше вариантов.

Навернуть можно много чего, вопрос зачем?
Конкретный пример наворота присутствовал в первом примере с которого топик начался. Наворот виден и кушает такты. Польза от наворота? Не писать в каждом обработчике в VICVectAddr? А если я, простите
захочу разрешить в одном (только упаси боже не во всех зараз) обработчике вложенные прерывания?
Нафига мне тогда такой сервис?


Во первых я сам в LPC пользую
Код
ldr     pc,[pc,#-0xFF0]

При этом я не пользую ОС.

Во вторых мы перевели разговор в сторону прерываний в ОС.
Цитата
А вот с этого места, пожалуйста поподробнее. Очень люблю про OSы думать. Заинтриговали.

ОС-ы бывают большие и маленькие, простые и сложные.
Писать их может один человек, а может и тысяча.

Ну и как пример оправданности оверхеда с тем же VICVectAddr:
Допустим Вы участвуете в разработке некой ОС или драйверов к ней.
Допустим Вам надо написать драйвер UART совместимого с x550.
Помимо всего прочего в драйвере нужен обработчик прерывания от UART-а.
Теперь вопрос: Вы хотите при этом досканально изучить все платформы на которых работает эта ОС (ну или по крайней мере есть UART совместимый с x550) и все возможные контроллеры прерываний на этих платформах чтобы использовать эти прерывания?
zltigo
Цитата(Alex03 @ Nov 28 2006, 11:31) *
У меня нет желания спорить с Вами.

Постараюсь тоже не спорить, но смолчать как-то не хочется. Вот такая проблема :-)

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

Цитата
И где по Вашему этим система разбирается?
1. Исполняется юзер-процесс
2. Происходит прерывание
3. Исполняется Ваш обработчик, который выводит из спячки высокоприоритетный процесс.
4. Возврат из прерывания
5. ??? Опять юзер-процесс ??? Где переключение контекста на высокоприоритетный процесс?

В пункте '3' когда обработчик "выводит из спячки высокоприоритетный процесс" по крайней мере
у меня так :-) - после перепланирования очереди задач планировщик возвращает признак наличия
более приоритетного процесса. При наличии более приоритетного дальнейшее поведение может быть
двояким;
- Ну есть и есть - проигнорировали и тогда в пункте 5 - все по Вашему - вернулись в прерванный процесс. И потом уже при ближайшем таймерном система перекючит.
- Вызвали переключатель контекста и тогда из обработчика возвратились уже в высокоприоритетный процесс.
По любому - статистикой системы занимаются вставки в системных вызовах а не универсальная прокладка перед обработчиками прерываний.

Цитата
Рядом с упомянутыми массивами nIntCounts[N], pIntFn[N] положите ещё массив с флагами для каждого прерывания, такими как возможность разрешения вложенности, флаг реентерабельности (повторного вхождения) и т.д.

Мысль понятна, реализация универсальна, но громоздка.
Цитата
и приходится ОС (точнее её универсальному обработчику прерывания) вызывать по очереди все зерегистрированные для данной линии обработчики, а уже конкретный обработчик первым делом проверяет своё железо на факт наличия прерывания,

Упустил, "про свои 16" - это однотипные девайсы про которые все знает их обработчик. Других, о которых он не знает - нет. Если мы на одно прерывание вешаем разнотипные железяки, то тогда, естественно некий супервизор необходим.

Цитата
Про обязательность везде и всего я не говорил. smile.gif

Это радует :-) Будем считать, что я про НЕ обязательность везде не говорил :-)
Однако в Ваших примерах просматривается жесткий перекос в большие системы, а я как-то ожидал, даже при упоминании слова "система" говорить о более приземленных материях.

Цитата
Во первых я сам в LPC пользую
ldr pc,[pc,#-0xFF0]
При этом я не пользую ОС.

А я пользую и то и другое. Причем, даже после вышеприведенного не буду менять концепцию :-)

Цитата
Ну и как пример оправданности оверхеда с тем же VICVectAddr:

В в системе эта проблема может решаться разными способами, например окончанием обработчика прерывания "системным вызовом", в вырожденном случае заменяющимся макросом с
"с тем же VICVectAddr". Ну и обертку делать тоже никто не запрещает. Это мне много ближе, нежели включение в систему абстрактно написанного драйвера, вызываемого из абстрактного кода. При таком подходе тот-же помянутый оверхед становится далеко не единственным :-(
Alex03
Цитата(zltigo @ Nov 28 2006, 15:38) *
По "статистике прерываний" - замну для ясности, хотя понятно, что делать абстракную статистику всех
прерываний правильнее в "узком месте", непонятно только зачем "всех". Точнее отсылка была явная
- если система большая и универсальная - пусть и это фиксирует, вдруг кто спросит.


При отладке (а то и при выяснении причин странного поведения) порой очень помагает.

Цитата
Цитата

И где по Вашему этим система разбирается?
1. Исполняется юзер-процесс
2. Происходит прерывание
3. Исполняется Ваш обработчик, который выводит из спячки высокоприоритетный процесс.
4. Возврат из прерывания
5. ??? Опять юзер-процесс ??? Где переключение контекста на высокоприоритетный процесс?

В пункте '3' когда обработчик "выводит из спячки высокоприоритетный процесс" по крайней мере
у меня так :-) - после перепланирования очереди задач планировщик возвращает признак наличия
более приоритетного процесса. При наличии более приоритетного дальнейшее поведение может быть
двояким;
- Ну есть и есть - проигнорировали и тогда в пункте 5 - все по Вашему - вернулись в прерванный процесс. И потом уже при ближайшем таймерном система перекючит.
- Вызвали переключатель контекста и тогда из обработчика возвратились уже в высокоприоритетный процесс.


Про дальнейший шедулинг по таймеру (или если задача сама отдала управление) - понятно, оно в данном контексте не интересно.
А если у вас 10 разных девайсов/прерываний и все они могут оживлять высокоприоритетные процессы? Во всех обработчиках проверять и вызывать переключатель контекста?
А может всё это вынести в одно место?

Цитата
По любому - статистикой системы занимаются вставки в системных вызовах а не универсальная прокладка перед обработчиками прерываний.


Вот тут не факт.
ИМХО во первых разделение system/user тайм гораздо полезнее не с точки зрения оценки времени исполнения кода user процесса(ов) и кода ядра/драйверов, а с точки зрения оценки времени "работы" процесса(ов) (сам процесс и его системные вызовы, за исключением ожидания событий в них) и времени работы ядра на обслуживание системы (шедулинг, прерывания и т.д.)
Во вторых как вы оцените время потраченное на исполнение некоего юзер-процесса, если во время его исполнения постоянно "молотят" никак к нему не относящиеся прерывания.

Цитата
Это радует :-) Будем считать, что я про НЕ обязательность везде не говорил :-)
Однако в Ваших примерах просматривается жесткий перекос в большие системы, а я как-то ожидал, даже при упоминании слова "система" говорить о более приземленных материях.


Был вопрос про примеры, я привёл, понятно что в простых ОС всё это не надо.
А перекос видимо потому что драйвера под линукс писал.

Цитата
А я пользую и то и другое. Причем, даже после вышеприведенного не буду менять концепцию :-)


Так и не надо.
Необходимость и достаточность - наше всё! smile.gif

У меня вон волосы дыбом вставали когда я видел что в ADSL-модеме на базе линукса светодиодом по CRON-у моргают типа "cat строка > /dev/led", а потом подумал а почему бы и нет, если им мощи хватает, а время на разработку нифига не дешевое.
zltigo
Цитата(Alex03 @ Nov 28 2006, 15:40) *
А перекос видимо потому что драйвера под линукс писал.

Заметно smile.gif.
Цитата
Необходимость и достаточность - наше всё! smile.gif

В embedded пока так.
Но к такому
Цитата
... в ADSL-модеме на базе линукса светодиодом по CRON-у моргают типа "cat строка > /dev/led", а потом подумал а почему бы и нет, если им мощи хватает, а время на разработку нифига не дешевое.

уже идет.
sensor_ua
У меня работает чуток рихтанутый вариант обработчика UART-а оттуда -> http://www.siwawi.arubi.uni-kl.de/avr_proj...s/#lpc_uart_irq
http://www.siwawi.arubi.uni-kl.de/avr_proj...rq_20051008.zip
Там используется while по биту interrupt-pending IIR
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.