|
|
  |
Вложенные прерывания в IAR, Как разрешить? |
|
|
|
Nov 23 2012, 05:19
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Нет этого мало. Нужно также в самом конце обработчика снова заблокировать прерывания, т.к. если вы посмотрите на то, что делает компилятор при выходе из прерывания, вы сможете обнаружить раскрутку стека и присвоение 16-ти битному регистру SP некого значения, так вот, модификация этого регистра должна быть атомарной операцией... В gcc есть специальные атрибуты у обработчиков прерывания, которые разрешают вложенность. Возможно, у ИАРа тоже есть нечто подобное. Код ISR(TIMER0_COMP_vect, ISR_NOBLOCK) { /* Code */ } Что касается глубины стека - это вам виднее, мы не знаем сложность вашей программы и её требования к стеку.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Nov 23 2012, 06:32
|
Профессионал
    
Группа: Свой
Сообщений: 1 719
Регистрация: 13-09-05
Из: Novosibirsk
Пользователь №: 8 528

|
Цитата(demiurg_spb @ Nov 23 2012, 12:19)  Нет этого мало. Нужно также в самом конце обработчика снова заблокировать прерывания, т.к. если вы посмотрите на то, что делает компилятор при выходе из прерывания, вы сможете обнаружить раскрутку стека и присвоение 16-ти битному регистру SP некого значения, так вот, модификация этого регистра должна быть атомарной операцией... У IARа этих проблем нет, так как SP используется только для хранения адресов возврата, а стек данных у них отдельно, регистровая пара Y используется как указатель стека данных.
--------------------
Russia est omnis divisa in partes octo.
|
|
|
|
|
Nov 23 2012, 07:24
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Цитата(SSerge @ Nov 23 2012, 10:32)  У IARа этих проблем нет, так как SP используется только для хранения адресов возврата, а стек данных у них отдельно, регистровая пара Y используется как указатель стека данных. И что? регистровая пара Y тоже двухбайтная. Что случится если изменили только её один байт, а в это время приходит вложенное прерывание и начинает выделять для себя место на стеке по кривому указателю Y. Или вы хотите сказать что в ИАРе прерывания не используют стек данных вовсе? Если так, то вы правы. Подтвердите или опровергните эту мысль пожалуйста. Более того если в прерывании вызывается какая-либо функция то она спокойно может использовать программный стек в своих целях как угодно. Так что я не вижу никакой принципиальной разницы между iar и avr-gcc в этом вопросе.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Nov 23 2012, 07:41
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
Цитата(demiurg_spb @ Nov 23 2012, 11:24)  И что? регистровая пара Y тоже двухбайтная. Что случится если изменили только её один байт, а в это время приходит вложенное прерывание и начинает выделять для себя место на стеке по кривому указателю Y. Или вы хотите сказать что в ИАРе прерывания не используют стек данных вовсе? Если так, то вы правы. Подтвердите или опровергните эту мысль пожалуйста. IAR в большинстве случаев использует атомарные операции и не обращается к Y по частям! ST -Y, LD Y+, SBIW, ADIW так что никаких конфликтов нет! Исключение если размер локальных переменных функции больше 64 байтов или параметров в стеке слишком много. Но такое для АВР редкость, а в прерываниях вообще не должно быть такого кода. И кстати тогда бы и в обычных функциях надо было бы перед выходом запрещать прерывания  Это как раз у GNU проблемы из-за того что стек один используют, а регистра нормального нет! В итоге код оптимальный только если в регистры все помещается, если нет - то все равно Y используют как BP, но код входа и выхода из функции кривой с запретом прерываний!
|
|
|
|
|
Nov 23 2012, 09:34
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 951
Регистрация: 27-08-04
Из: Санкт-Петербург
Пользователь №: 555

|
Цитата(demiurg_spb @ Nov 23 2012, 12:04)  Вовсе нет обычные push-pop, а запрет лишь когда нужно большой объект на стеке разместить, не влезающий в регистры или передать адрес стекового объекта куда-либо глубже. А это не столь частое явление. Уверен что и IAR тоже. Посмотрите как он выделит место под локальный масив или структуру размером 64 байта и более. Неужели он допрёт дважды - трижды или N-раз подряд ADIW использовать чтобы сдвинуть стек на нужное кол-во байт. Если так - респект ему и я умолкаю. Так я об этом и говорю! Особенно в прерываниях, а у GCC даже если хоть один байт из стека нужен под локальные данные, надо прерывания запрещать! Цитата(demiurg_spb @ Nov 23 2012, 12:04)  Неужели он допрёт дважды - трижды или N-раз подряд ADIW использовать чтобы сдвинуть стек на нужное кол-во байт. Если так - респект ему и я умолкаю. Допрет, проверил, даже 3 версия IAR так делала. Для AVR сравнивать GCC и IAR бесполезно - IAR вне конкуренции, начиная с более правильного calling conversion. Код получается и меньше и быстрее. GNU в принципе IAR не догнать пока calling conversion не поменяют!
|
|
|
|
|
Nov 23 2012, 13:26
|

Местный
  
Группа: Участник
Сообщений: 253
Регистрация: 4-03-09
Из: Богота, Колумбия
Пользователь №: 45 676

|
На другом форуме вот что сказали: "Блокирует, при входе в прерывание аппаратно сбрасывается бит I глобального разрешения. Можно программой его установить, и тогда будет возможно ещё одно. Только вначале нужно сбросить флаг предыдущего прерывания, т.к. аппаратно он сбрасывается только командой RETI - иначе если приоритет этого выше, контроллер зациклится и переполнение стека" В хелпе ИАРа никаких допдиректив для объявления прерывания не нашёл. Цитата(demiurg_spb @ Nov 23 2012, 08:19)  Что касается глубины стека - это вам виднее, мы не знаем сложность вашей программы и её требования к стеку. Я про это:
|
|
|
|
|
Nov 23 2012, 13:50
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(Dikoy @ Nov 23 2012, 15:26)  На другом форуме вот что сказали: "Только вначале нужно сбросить флаг предыдущего прерывания, т.к. аппаратно он сбрасывается только командой RETI - иначе если приоритет этого выше, контроллер зациклится и переполнение стека" Чушь какая-то: приоритеты, флаги... Обычно так делаю: Код #pragma vector=TIMER0_OVF_vect __interrupt void timer_1khz_isr(void) { unsigned char tmp_byte, new_byte; TCCR0 = 0x00; TIMSK &= ~(1 << TOIE0); __enable_interrupt(); // обработка прерывания // выход из прерывания __disable_interrupt(); TIMSK |= (1 << TOIE0); } Цитата(Dikoy @ Nov 23 2012, 15:26)  В хелпе ИАРа никаких допдиректив для объявления прерывания не нашёл. Есть кстати директива __nested (если не попутал чего): Код #pragma vector=TIMER0_OVF_vect __interrupt __nested void timer_1khz_isr(void) {
} Цитата(Dikoy @ Nov 23 2012, 15:26)  Я про это: Про это: Код #include <string.h>
#pragma segment="CSTACK" #pragma segment="RSTACK" unsigned char *dbg_ptr, *dbg_begin; #pragma inline=forced inline void FillStacks() { unsigned short stack_size; // заполнение стека данных stack_size=(unsigned char *)__segment_end("CSTACK")-(unsigned char *)__segment_begin("CSTACK"); memset(__segment_begin("CSTACK"), 'D', stack_size-10); //// очистка стека возвратов dbg_ptr=(unsigned char *)SP; dbg_ptr-=6; dbg_begin=(unsigned char *)__segment_begin("RSTACK"); // заполнение стека возвратов символом 'R' memset(dbg_begin, 'R', dbg_ptr-dbg_begin); } __noreturn int main(void) {
FillStacks(); while (1) { } }
|
|
|
|
|
Nov 23 2012, 14:11
|
Гуру
     
Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322

|
Цитата(demiurg_spb @ Nov 23 2012, 16:04)  Да нет. Всё верно ему сказали. Ну не всё верно: Цитата Только вначале нужно сбросить флаг предыдущего прерывания, т.к. аппаратно он сбрасывается только командой RETI Аппаратно флаги сбрасываются (не все наверное) при переходе на вектор, а не при выполнении RETI.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|