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

 
 
> Вложенные прерывания, GCC и ARM7
Novichok1
сообщение Mar 1 2010, 05:08
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 73
Регистрация: 8-07-09
Пользователь №: 51 032



Доброго времени суток!
Работаю с платой LPC2478, требуется реализовать вложенные (nested) прерывания.
Нарыл несколько статей на эту тему, но пока ни один метод не запахал.
Тестирую прерывания таким образом:

Код
void TestInterrupts::TestTimers()
{
    myPrintf("\nSTART TestTimers()\n");

    Timer0VICInit(Timer0ISR);
    Timer1VICInit(Timer1ISR);
    Timer1StartWithInt(1000);

    myPrintf("\nEND TestTimers()\n");
}

void TestInterrupts::Timer0ISR()
{
    T0IR  = TIR_MR0_INT; // reset interrrupt flags
    myPrintf("\nTimer0ISR()\n");
    // Dummy write to VIC to signal end of interrupt
    VICVectAddr = 0x00000000;
}

void TestInterrupts::Timer1ISR()
{
    IENABLE;

    T1IR  = TIR_MR0_INT; // reset interrrupt flags
    myPrintf("\nSTART Timer1ISR()\n");
        Timer0StartWithInt(5000);
    volatile tU8 dummy = 0;
    while(1)
    {
        dummy = 0;
    }
    myPrintf("\nEND Timer1ISR()\n");
    IDISABLE;
    // Dummy write to VIC to signal end of interrupt
    VICVectAddr = 0x00000000;
}


Где в качестве IENABLE пробовал разные последовательности ассемблерных команд, вычитанных с разных статей:
Код
// FROM Nesting of interrupts in the LPC2000 (AN10381)
#define IENABLE /* Nested Interrupts Entry */ \
        __asm__ ("MRS LR, SPSR"); /* Copy SPSR_irq to LR */ \
        __asm__ ("STMFD SP!, {LR}"); /* Save SPSR_irq */ \
        __asm__ ("MSR CPSR_c, #0x1F"); /* Enable IRQ (Sys Mode) */ \
        __asm__ ("STMFD SP!, {LR}"); /* Save LR */ \

Код
// FROM Real-time processing with the Philips LPC ARM microcontroller; using GCC and the MicroC/OS-II RTOS.
#define IENABLE /* Nested Interrupts Entry */ \
        __asm__ ("sub lr, lr, #4"); /* (1) Save IRQ context, including the APCS registers, and r4-6 */ \
        __asm__ ("stmfd sp!, {r0-r6, ip, lr}"); \
        __asm__ ("mrs r4, spsr"); /* (2) Save the SPSR_irq register */ \
        __asm__ ("ldr r5, =0xFFFFFF00"); /* (3) Read the VICVectAddr */ \
        __asm__ ("ldr r6, [r5]"); \
        __asm__ ("msr cpsr_c, 0x1F"); /* (4) Change to SYS mode and enable IRQ */ \
        __asm__ ("stmfd sp!, {lr}"); /* (5) Save the banked SYS mode link register */ \


То есть, на консоли должно появиться
Цитата
START TestTimers()
END TestTimers()
START Timer1ISR()
START Timer0ISR()


А на самом деле последняя строка не выводиться, что говорит о невхождении в обработчик вложенного прерывания Timer0.
Так вот, первый мой вопрос, какая же все таки последовательной команд должна быть в прологе и эпилоге обработчика для LPC2478?

И еще, во втором случае IENABLE полное описание вхождения и вывода их вложенных прерываний выглядит так:
Цитата
nested_irq_isr:
/* (1) Save IRQ context, including the APCS registers, and r4-6 */
sub lr, lr, #4
stmfd sp!, {r0-r6, ip, lr}
/* (2) Save the SPSR_irq register */
mrs r4, spsr
/* (3) Read the VICVectAddr */
ldr r5, VICVECTADDR
ldr r6, [r5]
/* (4) Change to SYS mode and enable IRQ */
msr cpsr_c, #SYS_MODE
/* (5) Save the banked SYS mode link register */
stmfd sp!, {lr}
/* (6) Call the C-coded handler */
mov lr, pc
ldr pc, r6
/* (7) Restore SYS mode link register */
ldmfd sp!, {lr}
36
AR1803 May 10, 2006
/* (8) Change to IRQ mode and disable IRQ */
msr cpsr_c, #IRQ_MODE|IRQ_DISABLE
/* (9) Restore the SPSR */
msr spsr, r4
/* (10) Acknowledge the VIC */
mov r0, #0
str r0, [r5]
/* (11) Restore IRQ context and return from interrupt */
ldmfd sp!, {r0-r6, ip, pc}^


И это описание натолкнуло меня на дополнительный вопрос, а можно ли в GCC переопределять последовательность операций для вызова функций, например путем создания собственных атрибутов для функций. И дальнейшим их использованием в примерно таком виде:
Код
static void Timer0ISR()  __attribute__ ((my_nested_interrupt))


Сообщение отредактировал Novichok1 - Mar 1 2010, 05:14
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Novichok1
сообщение Mar 4 2010, 05:44
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 73
Регистрация: 8-07-09
Пользователь №: 51 032



Хорошо, частично разобрался, для вызовов всех прерываний использую

Код
HandlerIRQ_ISR_NESTED:
    /* (1) Save IRQ context, including the APCS registers, and r4-6 */
    sub lr, lr, #4
    stmfd sp!, {r0-r6, ip, lr}
    /* (2) Save the SPSR_irq register */
    mrs r4, spsr
    /* (3) Read the VICVectAddr */
    ldr r5, =0xFFFFFF00
    ldr r6, [r5]
    /* (4) Change to SYS mode and enable IRQ */
    msr cpsr_c, #0x1F
    /* (5) Save the banked SYS mode link register */
    stmfd sp!, {lr}
    /* (6) Call the C-coded handler */
    mov lr, pc
    ldr pc, [r5]
    /* (7) Restore SYS mode link register */
    ldmfd sp!, {lr}
    /* (8) Change to IRQ mode and disable IRQ */
    msr cpsr_c, #Mode_IRQ|I_Bit
    /* (9) Restore the SPSR */
    msr spsr, r4
    /* (10) Acknowledge the VIC */
    mov r0, #0
    str r0, [r5]
    /* (11) Restore IRQ context and return from interrupt */
    ldmfd sp!, {r0-r6, ip, pc}^


И что происходит, в обработчике внешнего прерывания в цикле просматриваю флаги прерываний, и вижу, что да, второе прерывание срабатывает, но его обработчик не запуститься до тех пор, пока мы не запишем что-либо в VicVectAddr, что сделает возможными и прерывания меньшего приоритета
Цитата
Writing to the VICVECTADDR Register indicates to the interrupt priority hardware that the current interrupt is serviced, enabling lower priority or the same priority interrupts to be removed, and for the interrupts to become active to go active

И тем более запись в VicVectAddr советуют делать в самом конце обработчика прерывания, а без этой записи ядру не идет сообщение о прерывании. Может есть другой способ разрешить VIC инициализировать прерывания, без записи в VicVectAddr?


И еще, если использовать директивы компилятора, указывающими на то что данная функция является обработчиком прерывания, то компилятор сам сохраняет изменяемые регистры, а тут мы это делаем ручками и для всех обработчиков, поэтому возникает вопрос, а достаточно ли сохранение первых семи регистров(stmfd sp!, {r0-r6, ip, lr})?

И еще, небольшое наблюдение- приведенный выше подход проявляет более лучшую устойчивость, чем этот:
Цитата
#define IENABLE /* Nested Interrupts Entry */ \
__asm__ ("MRS LR, SPSR"); /* Copy SPSR_irq to LR */ \
__asm__ ("STMFD SP!, {LR}"); /* Save SPSR_irq */ \
__asm__ ("MSR CPSR_c, #0x1F"); /* Enable IRQ (Sys Mode) */ \
__asm__ ("STMFD SP!, {LR}"); /* Save LR */ \

// Macro for disabling interrupts, switching back to IRQ and relevant stack operations
#define IDISABLE /* Nested Interrupts Exit */ \
__asm__ ("LDMFD SP!, {LR}"); /* Restore LR */ \
__asm__ ("MSR CPSR_c, #0x92"); /* Disable IRQ (IRQ Mode) */ \
__asm__ ("LDMFD SP!, {LR}"); /* Restore SPSR_irq to LR */ \
__asm__ ("MSR SPSR_cxsf, LR"); /* Copy LR to SPSR_irq */ \


Так, если в обработчике первого прерывания происходит второе прерывания, а в вызванном обработчике второго прерывания происходит первое, то после выхода из обработчика программа глючит.

Сообщение отредактировал Novichok1 - Mar 4 2010, 06:25
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Novichok1   Вложенные прерывания, GCC и ARM7   Mar 1 2010, 05:08
- - sergeeff   Про прерывания а форуме для ARM столько уже понапи...   Mar 1 2010, 06:57
- - Novichok1   Цитата1. Заставить VIC вызывать по прерыванию С++ ...   Mar 1 2010, 08:07
- - Novichok1   Может и правда, дело в стартапе, выложу его на вся...   Mar 1 2010, 09:12
- - Novichok1   И благодаря такому подходу исчезли глюки, которые ...   Mar 4 2010, 07:06
- - GetSmart   театр одного актёра   Mar 4 2010, 23:26
- - aaarrr   Цитата(GetSmart @ Mar 5 2010, 02:26) теат...   Mar 4 2010, 23:57
|- - Novichok1   Цитата(aaarrr @ Mar 5 2010, 02:57) Перед ...   Mar 5 2010, 04:59
|- - aaarrr   Цитата(Novichok1 @ Mar 5 2010, 07:59) Бол...   Mar 5 2010, 10:04
|- - GetSmart   Цитата(aaarrr @ Mar 5 2010, 15:04) Вложен...   Mar 5 2010, 12:14
||- - Novichok1   Цитата(GetSmart @ Mar 5 2010, 15:14) Это ...   Mar 5 2010, 12:43
||- - GetSmart   Цитата(Novichok1 @ Mar 5 2010, 17:43) То ...   Mar 5 2010, 12:54
||- - Novichok1   Цитата(GetSmart @ Mar 5 2010, 15:54) То б...   Mar 5 2010, 13:12
|- - Novichok1   Цитата(aaarrr @ Mar 5 2010, 13:04) Вложен...   Mar 5 2010, 12:23
- - GetSmart   Цитата(Novichok1)Вот и складывается впечатление, ч...   Mar 5 2010, 06:44
- - Novichok1   Ну точнее, там используется два источника прерыван...   Mar 5 2010, 07:22
- - GetSmart   Если после команды ldmfd в эпилоге второго ничего ...   Mar 5 2010, 07:43
|- - Novichok1   Цитата(GetSmart @ Mar 5 2010, 10:43) Если...   Mar 5 2010, 07:47
- - GetSmart   ЦитатаВсе-таки кажется странным, что некорректный ...   Mar 5 2010, 12:35
|- - Novichok1   Цитата(GetSmart @ Mar 5 2010, 15:35) Со с...   Mar 5 2010, 12:55
- - aaarrr   Цитата(Novichok1 @ Mar 5 2010, 15:23) А н...   Mar 5 2010, 12:41
- - GetSmart   Это не свой атрибут, а стандартный. Используется т...   Mar 5 2010, 13:03
- - GetSmart   Цитата(Novichok1)Спасибо, а не в курсе, Не, не в к...   Mar 5 2010, 14:03
- - GetSmart   Novichok1, хотел ещё спросить, зачем было делать о...   Mar 11 2010, 12:21
- - Novichok1   А разве к статическим членам нет доступа? Ведь обр...   Mar 11 2010, 15:07
- - GetSmart   Я бы всё таки выделил прерывания из класса. ИМХО э...   Mar 11 2010, 16:35
|- - Novichok1   Цитата(GetSmart @ Mar 11 2010, 20:35) Зна...   Mar 11 2010, 18:22
- - GetSmart   Вообще, излишняя универсальность, которая не понад...   Mar 11 2010, 19:02
|- - Novichok1   Цитата(GetSmart @ Mar 11 2010, 22:02) А ч...   Mar 12 2010, 04:49
- - GetSmart   Цитата(Novichok1)Но в любом случае, мне не совсем ...   Mar 12 2010, 05:50
- - Aurochs   Цитата(GetSmart @ Mar 12 2010, 07:50) Так...   Mar 13 2010, 18:30


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

 


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


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