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

 
 
> Прерывания без ОС на EP9315, обработчик не вызывается
toykhee_menky
сообщение Jun 30 2008, 15:43
Сообщение #1





Группа: Новичок
Сообщений: 9
Регистрация: 30-06-08
Пользователь №: 38 654



Здравствуйте.

EP9315 на плате Tion-pro v1.
Программа на Си, компилируется WinARM 4.1.1, грузится в RAM при помощи redboot.

Пытаюсь работать с портом UART2, порт, судя по всему, работает - тестовая последовательность туда уходит.

FIFO разрешено, после посылки восьми символов оттуда появляется битик прерывания в VIC1RawIntr, т.е. прерывание до VIC вроде бы доходит.

По адресу 0x18 содержится команда, оставленная там redboot-ом, судя по всему:
00000018: 18 F0 9F E5 - перевожу как ldr r15,[r15,#0x18], т.е. должен взяться адрес процедуры реакции на прерывание с адреса 0x38 (0x18+0x18+0x08).

Подменяю указатель по адресу 0x38 на адрес своей функции. Но управление она не получает (контроль - светодиодами).

Прерывания разрешены, режим супервизора: cpsr=0x00000013
ОЗУ отмаплено само на себя, с адреса 0.

обработчик прерывания IRQ оформлен как
Код
void  __attribute__ ((interrupt ("IRQ"))) handler1();

но управления тоже не получает (источник прерывания 25 для VIC1 выбрал, прерывания разрешил, адрес ISR занес).

Чего-то я еще не сделал... Чего?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
aaarrr
сообщение Jun 30 2008, 16:00
Сообщение #2


Гуру
******

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



VIC, наверное, неправильно инициализировали. Код приведите.

Стоп.
Цитата
Подменяю указатель по адресу 0x38 на адрес своей функции.

А VIC что, оказался совсем не у дел? Процессор будет падать на этот адрес по любому прерыванию.
Go to the top of the page
 
+Quote Post
toykhee_menky
сообщение Jun 30 2008, 16:21
Сообщение #3





Группа: Новичок
Сообщений: 9
Регистрация: 30-06-08
Пользователь №: 38 654



Цитата(aaarrr @ Jun 30 2008, 22:00) *
VIC, наверное, неправильно инициализировали. Код приведите.
Не уверен, что нужно всё подряд, вот части, непосредственно работающие с VIC1:
Код
#define IRQ_SRC 25
volatile unsigned int    *VIC1IRQStatus=(unsigned int *)0x800B0000u;
volatile unsigned int    *VIC1FIQStatus=(unsigned int *)0x800B0004u;
volatile unsigned int      *VIC1RawIntr=(unsigned int *)0x800B0008u;
volatile unsigned int    *VIC1IntSelect=(unsigned int *)0x800B000Cu;
volatile unsigned int    *VIC1IntEnable=(unsigned int *)0x800B0010u;
volatile unsigned int   *VIC1IntEnClear=(unsigned int *)0x800B0014u;
volatile unsigned int            *VIC1protection=(int *)0x800b0020u;
volatile unsigned int     *VIC1VectAddr=(unsigned int *)0x800B0030u;
volatile unsigned int  *VIC1DefVectAddr=(unsigned int *)0x800B0034u;
volatile unsigned int    *VIC1VectAddr0=(unsigned int *)0x800B0100u;
volatile unsigned int    *VIC1VectCntl0=(unsigned int *)0x800B0200u;

volatile int *pedr=(int *)0x80840020u;
unsigned int old_0x38;
unsigned int *ptr_0x38=(unsigned int *)0x38;



Код
  *pedr=3;
  old_0x38= *ptr_0x38;
  *ptr_0x38 = (unsigned int)irq_handler;


пробовал nirq=0 и =4, одинаково:

Код
  VIC1VectAddr0[nirq]=(unsigned int)handler1;
  // 2) chain to 25 source (IRQ_SRC)

  VIC1VectCntl0[nirq]=     IRQ_SRC;
  VIC1VectCntl0[nirq]=0x20|IRQ_SRC;

  // 3) enable it
  *VIC1IntEnable = (1<<IRQ_SRC);
и прибиваю торчащее откуда-то прерывание от источника 3:
Код
*VIC1IntEnClear = 0x08;
*VIC1DefVectAddr=(unsigned int)handler1;

Тексты двух обработчиков:
Код
// -------------- handler1 ----------------------
void __attribute__ ((interrupt ("IRQ"))) handler1()
{
    //volatile unsigned int *VIC1VectAddr=(unsigned int *)0x800B0030;
    //volatile unsigned int *VIC2VectAddr=(unsigned int *)0x800C0030;

    unsigned int s= *VIC1VectAddr;

    while (((*UART2Flag) & 0x10)==0) {
    int k= *UART2Data;
        rs_data_in[rs_h++]=k;
        if (rs_h>=MAX_RS_DT)
           rs_h=0;
    }
    *pedr=2;

    *VIC1VectAddr=0;

};
// --------------- irq_handler ------------------
void irq_handler(void)
{
      asm("stmfd sp!, {r0-r12, lr}");
      void (*interrupt_function)();
      unsigned int vector;
      *pedr=0;
      vector = *VIC1VectAddr;
      interrupt_function = (void(*)())vector;
      (*interrupt_function)();
      *VIC1VectAddr = 0;
      
      asm("ldmfd sp!, {r0-r12, lr}");
      asm("subs pc, lr, #4");
}

В общем, не совсем понятно соотношение обработчиков по адресу 0x18, помещенных в вектор (VIC1VectAddr0..VIC1VectAddr15) и VIC1DefVectAddr.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 30 2008, 16:47
Сообщение #4


Гуру
******

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



Цитата(toykhee_menky @ Jun 30 2008, 20:21) *
В общем, не совсем понятно соотношение обработчиков по адресу 0x18, помещенных в вектор (VIC1VectAddr0..VIC1VectAddr15) и VIC1DefVectAddr.

Кто в кого помещен?

Код, если честно, мозг ломает напрочь. Но некоторые моменты могу прояснить:
- Читать и писать VectAddr нужно в одном месте, а не в двух.
- Оформлять процедуру в виде прерывания - тоже.

Т.е. если в irq_handler читается и пишется VectAddr, и оформлен он как irq (в чем я, кстати, не уверен - уж больно дикий микс asm-C), то handler1 должен быть простой процедурой.

Код
// -------------- handler1 ----------------------
void handler1(void)
{
      // Здесь ничего из VIC'а не трогаем
};
// --------------- irq_handler ------------------
void __attribute__ ((interrupt ("IRQ"))) irq_handler(void)
{
      unsigned int vector;

      vector = *VIC1VectAddr;
      ...
      *VIC1VectAddr = 0;
}


Но по-хорошему и так делать не следует, ибо очень криво.

Только сейчас заметил 07.gif 07.gif 07.gif :
Код
*VIC1DefVectAddr=(unsigned int)handler1;


Внимательно и вдумчиво почитайте мануал на VIC (есть на ARM'овском сайте) и архитектуру ARM.
Go to the top of the page
 
+Quote Post
toykhee_menky
сообщение Jun 30 2008, 20:01
Сообщение #5





Группа: Новичок
Сообщений: 9
Регистрация: 30-06-08
Пользователь №: 38 654



Цитата(aaarrr @ Jun 30 2008, 22:47) *
Кто в кого помещен?

см.внизу
Цитата(aaarrr @ Jun 30 2008, 22:47) *
Код, если честно, мозг ломает напрочь.

Я знаю; но это была Ваша инициатива.

Цитата(aaarrr @ Jun 30 2008, 22:47) *
Но некоторые моменты могу прояснить:
- Читать и писать VectAddr нужно в одном месте, а не в двух.
- Оформлять процедуру в виде прерывания - тоже.

Да, если бы программа работала, так бы и было. Но она не работает, но не потому же, что
тут в двух местах читается VectAddr? Ведь до handler1 управление не доходит, так же как и до irq_handler.
Цитата(aaarrr @ Jun 30 2008, 22:47) *
Т.е. если в irq_handler читается и пишется VectAddr, и оформлен он как irq (в чем я, кстати, не уверен - уж больно дикий микс asm-C), то handler1 должен быть простой процедурой.

Только сейчас заметил 07.gif 07.gif 07.gif :
Код
*VIC1DefVectAddr=(unsigned int)handler1;


Внимательно и вдумчиво почитайте мануал на VIC (есть на ARM'овском сайте) и архитектуру ARM.

Это я от отчаяния.

Читаю:
2.1.6 Vectored interrupts
A vectored interrupt is only generated if the following are true:
• you enable it in the interrupt enable register, VICIntEnable
• you set it to generate an IRQ interrupt in the interrupt select register, VICIntSelect
• you enable it in the relevant vector control register, VICVectCntl[0-15].

В соответствии с этим описанием никаких манипуляций с адресом 0x18 не требуется вообще.
Всего три пункта: правильная маска в VICIntEnable, правильная маска в VICIntSelect,
правильное значение VICVectCntl[0-15].

Код
  VIC1VectCntl0[nirq]=     IRQ_SRC;
  VIC1VectCntl0[nirq]=0x20|IRQ_SRC;

  // 3) enable it
  *VIC1IntEnable = (1<<IRQ_SRC);

AFAIR биты VICIntSelect имеют следующие значения: 0:IRQ, 1:FIQ.
По умолчанию 0, т.е. IRQ.

("кто в кого помещен") Интересно, что здесь даже не сказано о VIC1VectAddr0..VIC1VectAddr15. То есть даже если я не помещу туда никакое ненулевое значение, прерывание всё равно произойдет, и управление передастся по адресу 0. Допустим. Но этого не происходит.

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

При возникновении прерывания бит в VIC1RawIntr (да и в VIC1IRQStatus), соответствующий прерыванию от UART2 (номер 25) взводится. Да так и остается взведенным.

Вдумчиво читаю и комментирую еще одно положение:
2.2.1 Vectored interrupt flow sequence
The following procedure shows the sequence for the vectored interrupt flow:
1. An interrupt occurs.
- появляется прерывание. Да, появилось
2. The ARM processor branches to either the IRQ or FIQ interrupt vector.
- АРМ-процессор осуществляет переход либо на IRQ либо на FIQ-вектор. К сожалению, тут непонятно, о каком именно векторе идет речь. То ли о том, что определен как 0x18/0x1C, то ли о VICxVectAddr0..VICxVectAddr15.
3. If the interrupt is an IRQ, read the VICVectAddr Register and branch to the
interrupt service routine. You can do this using an LDR PC instruction. Reading the
VICVectorAddr Register updates the interrupt controllers hardware priority
register.

Если прерывание - IRQ (а что делать, если это не так?), прочитай регистр VICVectAddr и осуществи переход на ISR. Вы можете сделать это, используя инструкцию LDR PC. Считывание регистра VICVectorAddr обновляет аппаратный регистр приоритета контроллера прерываний.
о чем здесь идет речь? О процедуре, на которую управление приходит с адреса 0x18/0x1C.

4. Stack the workspace so that you can re-enable IRQ interrupts.
5. Enable the IRQ interrupts so that a higher priority can be serviced.
6. Execute the Interrupt Service Routine (ISR).

Выполнить ISR - коротко и ясно.

7. Clear the requesting interrupt in the peripheral, or write to the VICSoftIntClear
Register if the request was generated by a software interrupt.
8. Disable the interrupts and restore the workspace.
9. Write to the VICVectAddr Register. This clears the respective interrupt in the
internal interrupt priority hardware.
10. Return from the interrupt. This re-enables the interrupts.

Получается следующее. Поправьте меня, если я не прав.
* При возникновении IRQ-прерывания управление попадает по адресу 0x18, далее в процедуру обработки аппаратного прерывания, которая выясняет, было ли прерывание векторизированным или нет, выбирает соответствующий ISR, вызывает его, осуществляет манипуляции по повторному разрешению прерываний.
* Считывание и запись регистра VICVectAddr осуществляется соответственно до и после вызова ISR.
* ISR - обычная процедура

Прекрасно, я сейчас это всё сделаю. Только проблема-то останется - hardware handler не вызывается.

В этом же документе (DDI0181.pdf) описывается механизм быстрой обработки прерываний, когда VIC отмапливается на адрес 0xFFFFF000. Тогда его регистры становятся в пределах досягаемости от адреса 0x18, и можно разместить там команду LDR pc, [pc, #-0xff0]. При выполнении этой команды управление передастся на адрес, который хранится непосредственно в VIC, с учетом отмапливания это будет 0xFFFFF030, т.е. VICVectAddr. И в этом случае дополнительного считывания делать уже не нужно, уже всё прочитано и ушло на исполнение... нет?

У меня было несколько предположений. Рискну изложить их здесь, какими бы глупыми они ни были.
1. Прерывание не возникает, потому что процессор в режиме супервизора.
2. Прерывание возникает, но управление передается не на адрес 0x18.
3. Для того, чтобы изменения в VIC воспринялись, нужны дополнительные действия (аналогично outportb(0x20,0x20) в IBM PC).
4. Прерывание не возникает, потому что активно прерывание с более высоким приоритетом. Но я его не вижу.

Сообщение отредактировал toykhee_menky - Jun 30 2008, 20:04
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jul 1 2008, 12:09
Сообщение #6


Гуру
******

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



Цитата(toykhee_menky @ Jul 1 2008, 00:01) *
Получается следующее. Поправьте меня, если я не прав.
* При возникновении IRQ-прерывания управление попадает по адресу 0x18, далее в процедуру обработки аппаратного прерывания, которая выясняет, было ли прерывание векторизированным или нет, выбирает соответствующий ISR, вызывает его, осуществляет манипуляции по повторному разрешению прерываний.
* Считывание и запись регистра VICVectAddr осуществляется соответственно до и после вызова ISR.
* ISR - обычная процедура

Все правильно.

Цитата(toykhee_menky @ Jul 1 2008, 00:01) *
В этом же документе (DDI0181.pdf) описывается механизм быстрой обработки прерываний, когда VIC отмапливается на адрес 0xFFFFF000...
...И в этом случае дополнительного считывания делать уже не нужно, уже всё прочитано и ушло на исполнение... нет?

Да, это самый нормальный способ работы с VIC'ом. В прерывании остается только запись VICVectAddr.

Цитата(toykhee_menky @ Jul 1 2008, 00:01) *
У меня было несколько предположений. Рискну изложить их здесь, какими бы глупыми они ни были.
1. Прерывание не возникает, потому что процессор в режиме супервизора.
2. Прерывание возникает, но управление передается не на адрес 0x18.
3. Для того, чтобы изменения в VIC воспринялись, нужны дополнительные действия (аналогично outportb(0x20,0x20) в IBM PC).
4. Прерывание не возникает, потому что активно прерывание с более высоким приоритетом. Но я его не вижу.

1, Не бывает.
2. Может быть, если в регистре 1 CP15 установлен бит V, тогда вектора будут расположены с адреса 0xffff0000. Но вряд ли это так.
3. Никаких действий не нужно.
4. Попробуйте сбросить VIC шестнадцатикратной записью VICVectAddr.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- toykhee_menky   Прерывания без ОС на EP9315   Jun 30 2008, 15:43
- - sergeeff   Ну я бы под пунктом 0 добавил: Преравание не возни...   Jul 1 2008, 05:58
|- - toykhee_menky   Цитата(sergeeff @ Jul 1 2008, 11:58) Ну я...   Jul 1 2008, 06:30
- - sergeeff   Ну я бы, для начала, написал бы тестовую функцию о...   Jul 1 2008, 08:24
- - sergeeff   Можно посмотреть http://www.siwawi.arubi.uni-kl.de...   Jul 1 2008, 15:46
- - toykhee_menky   Мда. Проблема, однако. Неужели я один такой (или п...   Jul 2 2008, 11:14
- - aaarrr   Исходники redboot'а, если охота в них ковырять...   Jul 2 2008, 11:32
|- - toykhee_menky   Цитата(aaarrr @ Jul 2 2008, 17:32) Исходн...   Jul 2 2008, 13:14
- - sergeeff   Ну вот, осталось посмотреть, что же сидит в таблиц...   Jul 2 2008, 11:33
- - sergeeff   А что за процедура вызывается по прерыванию? Как б...   Jul 2 2008, 16:02
- - Desenix   для армов EP9312, S3C2410, LPC2368 всегда писал и ...   Jul 2 2008, 17:10
- - sergeeff   Все очень здорово, но надо же еще обучить процессо...   Jul 2 2008, 18:38
|- - Desenix   ну да, еще стандартный startup забыл приложить, за...   Jul 2 2008, 19:18
|- - toykhee_menky   Цитата(sergeeff @ Jul 3 2008, 00:38) Все ...   Jul 3 2008, 05:44
- - sergeeff   Уважаемый toykhee_menky! 1. Так про то и речь...   Jul 3 2008, 06:15
- - aaarrr   Цитата(toykhee_menky @ Jun 30 2008, 19:43...   Jul 3 2008, 08:25
|- - toykhee_menky   Цитата(aaarrr @ Jul 3 2008, 14:25) Да, а ...   Jul 3 2008, 13:08
- - aaarrr   Значит на ядро прерывание передается, других вариа...   Jul 3 2008, 13:15
- - sergeeff   Ну дак и осталось то, про что я уже говорил - напи...   Jul 3 2008, 14:12
- - toykhee_menky   Всем спасибо. Перешел на eCos.   Jul 12 2008, 13:49
- - sergeeff   Ну, флаг в руки! Думаю там заморочек будет ещ...   Jul 12 2008, 18:41


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

 


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


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