Цитата(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 должен быть простой процедурой.
Только сейчас заметил

:
Код
*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. Прерывание не возникает, потому что активно прерывание с более высоким приоритетом. Но я его не вижу.