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

 
 
> Вложенные прерывания, 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
Ответов
aaarrr
сообщение Mar 4 2010, 23:57
Сообщение #2


Гуру
******

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



Цитата(GetSmart @ Mar 5 2010, 02:26) *
театр одного актёра smile.gif

Надо помочь, наверное, да пугают длинные копипасты мутного кода.

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

Перед вызовом достаточно сохранить R0-R3, R12, R14, остальное вызываемая подпрограмма трогать не имеет права. R4-R6 портит сама обертка.
Кроме того, следует обратить внимание на некорректное выравнивание стека - должно быть четное число слов.
Использование одного обработчика для прерываний всех приоритетов - тоже, мягко говоря, не самая светлая идея.

Цитата(Novichok1 @ Mar 4 2010, 08:44) *
Так, если в обработчике первого прерывания происходит второе прерывания, а в вызванном обработчике второго прерывания происходит первое, то после выхода из обработчика программа глючит.

Не происходит такого в нормальных условиях. Пока выполняется один обработчик прерывания с определенным приоритетом, другие прерывания с тем же или меньшим приоритетом маскируются. Иначе какой вообще смысл во вложенности?
Go to the top of the page
 
+Quote Post
Novichok1
сообщение Mar 5 2010, 04:59
Сообщение #3


Участник
*

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



Цитата(aaarrr @ Mar 5 2010, 02:57) *
Перед вызовом достаточно сохранить R0-R3, R12, R14, остальное вызываемая подпрограмма трогать не имеет права. R4-R6 портит сама обертка.
Кроме того, следует обратить внимание на некорректное выравнивание стека - должно быть четное число слов.

Большое спасибо за разъяснение! А насчет некорректного выравнивания стека - после stmfd sp!, {r0-r6, ip, lr} через некоторое число команд вызывается еще и stmfd sp!, {lr} (на шаге 5), так что в сумме получается четное число сохраненных регистров, так можно рассуждать, или при выполнении ОДНОЙ команды записи в стек должно сохраняться четное число слов?

Цитата(aaarrr @ Mar 5 2010, 02:57) *
Использование одного обработчика для прерываний всех приоритетов - тоже, мягко говоря, не самая светлая идея.

Я наверно не совсем точно выразился, под " ...для вызовов всех прерываний использую..." не имелось ввиду использование одного сишного обработчика для всех прерываний, а подразумевалась последовательность ассемблерных команд для подготовки ко входу в обработчик прерывания, вызова сишной функции обработчика, адрес которой лежит в регистре ViсVectAddr, и восстановления регистров и состояния проца после завершения обработчика. Так что для каждого прерывания у меня свой обработчик, как и положено.

Цитата(aaarrr @ Mar 5 2010, 02:57) *
Не происходит такого в нормальных условиях. Пока выполняется один обработчик прерывания с определенным приоритетом, другие прерывания с тем же или меньшим приоритетом маскируются. Иначе какой вообще смысл во вложенности?

Вот в этом-то и дело! К примеру, если в процессе работы обработчика прерывания с приоритетом 5 (Timer1), происходит прерывание с приоритетом 4 (Timer0), то выставляются флаги прерывания в T0IR, VICIRQStatus, записывается нужный адрес в VicVecAddress, НО перехода в обработчик прерывания Timer0 не происходит до тех пор, пока мы не запишем что-либо в регистр VicVecAddress, что само собой разрешит прерывания всех приоритетов. Хотя ни в "AN10381(Nesting of interrupts in the LPC2000)", ни в "Real-time processing with the Philips LPC ARM microcontroller; using GCC and the MicroC/OS-II RTOS." про необходимость записи в регистр VicVecAddress для разрешения вложенных прерываний ничего не сказано. Там говорится о достаточности применения вышеописанных макросов IENABLE, IDISABLE, либо ассемблерной процедурине для входа и выхода из обработчика. Вот и интересно, что же я упустил?

А вообще, рассмотрение сего вопроса началось из-за следующего глюка: вызывается функция, которая допускает появления прерываний, далее походу при появлении этих прерываний, ИНОГДА появляются лишние вызовы функций со странными параметрами. При рассмотрении это было похоже на следующее:
1. Вызвали функцию Func1(param1),
2. В этой функции произошло прерывание, в котором использовалось значение по адресу param_ISR
3. Вышли из прерывания
4. ЛИШНИЙ повторный вызов функции Func1(param_ISR) (прошу обратить внимание на изменившийся параметр!)
5. Дальнейший ход выполнения программы.
Обработчик прерывания был отмечен атрибутом __attribute__ ((interrupt)), никаких макросов типа IENABLE не было, вход в обработчик был стандартным.
Вот и складывается впечатление, что при входе-выходе из прерывания сохраняются-ресторятся не все регистры.

Цитата
театр одного актёра

Благодарю за участие)

Сообщение отредактировал Novichok1 - Mar 5 2010, 05:17
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Mar 5 2010, 10:04
Сообщение #4


Гуру
******

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



Цитата(Novichok1 @ Mar 5 2010, 07:59) *
Большое спасибо за разъяснение! А насчет некорректного выравнивания стека - после stmfd sp!, {r0-r6, ip, lr} через некоторое число команд вызывается еще и stmfd sp!, {lr} (на шаге 5), так что в сумме получается четное число сохраненных регистров, так можно рассуждать, или при выполнении ОДНОЙ команды записи в стек должно сохраняться четное число слов?

На шаге 5 пишется уже другой стек (SYS), суммировать эти записи нельзя.

Цитата(Novichok1 @ Mar 5 2010, 07:59) *
Я наверно не совсем точно выразился, под " ...для вызовов всех прерываний использую..." не имелось ввиду использование одного сишного обработчика для всех прерываний, а подразумевалась последовательность ассемблерных команд для подготовки ко входу в обработчик прерывания

Я ее и имел в виду. Для прерывания с высшим приоритетом эта ассемблерная последовательность - пустая трата времени.

Цитата(Novichok1 @ Mar 5 2010, 07:59) *
Вот и интересно, что же я упустил?

Вложенные прерывания предполагают, что выполнение процедуры обработки прерывания с приоритетом 5 может быть прервано прерыванием с приоритетом 6 или выше. Прерывание с меньшим приоритетом (4) может отработать только после записи VicVectAddr.
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, 05:44
- - Novichok1   И благодаря такому подходу исчезли глюки, которые ...   Mar 4 2010, 07:06
- - GetSmart   театр одного актёра   Mar 4 2010, 23:26
|- - 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 - 23:15
Рейтинг@Mail.ru


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