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

 
 
 
Reply to this topicStart new topic
> Вложенные прерывания в IAR, Как разрешить?
Dikoy
сообщение Nov 23 2012, 04:14
Сообщение #1


Местный
***

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



Чтоб разрешить вложенные прерывания в AVR (IAR 6), надо просто сделать __enable_interrupt(); в начале тела обработчика?

Имеется ввиду вложенность, когда процу разрешается выходить из тела текущего обработчика прерывания, если возникло другое прерывание (любое).
Знаю, что это можно, но как-то до сих пор на АВР не пригождалось...
Стек левел нуждается в настройке? По умолчанию там 16.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Nov 23 2012, 05:19
Сообщение #2


неотягощённый злом
******

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



Нет этого мало. Нужно также в самом конце обработчика снова заблокировать прерывания, т.к. если вы посмотрите на то, что делает компилятор при выходе из прерывания, вы сможете обнаружить раскрутку стека и присвоение 16-ти битному регистру SP некого значения, так вот, модификация этого регистра должна быть атомарной операцией...
В gcc есть специальные атрибуты у обработчиков прерывания, которые разрешают вложенность. Возможно, у ИАРа тоже есть нечто подобное.
Код
ISR(TIMER0_COMP_vect, ISR_NOBLOCK)
{
/* Code */
}
Что касается глубины стека - это вам виднее, мы не знаем сложность вашей программы и её требования к стеку.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
SSerge
сообщение Nov 23 2012, 06:32
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 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.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Nov 23 2012, 07:24
Сообщение #4


неотягощённый злом
******

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



Цитата(SSerge @ Nov 23 2012, 10:32) *
У IARа этих проблем нет, так как SP используется только для хранения адресов возврата, а стек данных у них отдельно, регистровая пара Y используется как указатель стека данных.

И что? регистровая пара Y тоже двухбайтная. Что случится если изменили только её один байт, а в это время приходит вложенное прерывание и начинает выделять для себя место на стеке по кривому указателю Y. Или вы хотите сказать что в ИАРе прерывания не используют стек данных вовсе? Если так, то вы правы. Подтвердите или опровергните эту мысль пожалуйста.
Более того если в прерывании вызывается какая-либо функция то она спокойно может использовать программный стек в своих целях как угодно.
Так что я не вижу никакой принципиальной разницы между iar и avr-gcc в этом вопросе.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
KRS
сообщение Nov 23 2012, 07:41
Сообщение #5


Профессионал
*****

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



Цитата(demiurg_spb @ Nov 23 2012, 11:24) *
И что? регистровая пара Y тоже двухбайтная. Что случится если изменили только её один байт, а в это время приходит вложенное прерывание и начинает выделять для себя место на стеке по кривому указателю Y. Или вы хотите сказать что в ИАРе прерывания не используют стек данных вовсе? Если так, то вы правы. Подтвердите или опровергните эту мысль пожалуйста.

IAR в большинстве случаев использует атомарные операции и не обращается к Y по частям!
ST -Y, LD Y+, SBIW, ADIW так что никаких конфликтов нет!
Исключение если размер локальных переменных функции больше 64 байтов или параметров в стеке слишком много. Но такое для АВР редкость, а в прерываниях вообще не должно быть такого кода.

И кстати тогда бы и в обычных функциях надо было бы перед выходом запрещать прерывания wink.gif

Это как раз у GNU проблемы из-за того что стек один используют, а регистра нормального нет! В итоге код оптимальный только если в регистры все помещается, если нет - то все равно Y используют как BP, но код входа и выхода из функции кривой с запретом прерываний!
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Nov 23 2012, 08:04
Сообщение #6


неотягощённый злом
******

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



Цитата(KRS @ Nov 23 2012, 11:41) *
И кстати тогда бы и в обычных функциях надо было бы перед выходом запрещать прерывания wink.gif
avr-gcc так и делает когда применяет не атомарные инструкции по модификации стека. Уверен что и IAR тоже. Посмотрите как он выделит место под локальный масив или структуру размером 64 байта и более. Неужели он допрёт дважды - трижды или N-раз подряд ADIW использовать чтобы сдвинуть стек на нужное кол-во байт. Если так - респект ему и я умолкаю.

Цитата(KRS @ Nov 23 2012, 11:41) *
но код входа и выхода из функции кривой с запретом прерываний!
Вовсе нет обычные push-pop, а запрет лишь когда нужно большой объект на стеке разместить, не влезающий в регистры или передать адрес стекового объекта куда-либо глубже. А это не столь частое явление.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
KRS
сообщение Nov 23 2012, 09:34
Сообщение #7


Профессионал
*****

Группа: Модераторы
Сообщений: 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 не поменяют!



Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Nov 23 2012, 12:55
Сообщение #8


неотягощённый злом
******

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



Цитата(KRS @ Nov 23 2012, 13:34) *
GNU в принципе IAR не догнать пока calling conversion не поменяют!
Боюсь что уже не поменяют. Слишком уже глубоко вросло всё. Да и ещё есть над чем работать и без таких глобальных изменений.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Dikoy
сообщение Nov 23 2012, 13:26
Сообщение #9


Местный
***

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



На другом форуме вот что сказали:
"Блокирует, при входе в прерывание аппаратно сбрасывается бит I глобального разрешения. Можно программой его установить, и тогда будет возможно ещё одно. Только вначале нужно сбросить флаг предыдущего прерывания, т.к. аппаратно он сбрасывается только командой RETI - иначе если приоритет этого выше, контроллер зациклится и переполнение стека"
В хелпе ИАРа никаких допдиректив для объявления прерывания не нашёл.

Цитата(demiurg_spb @ Nov 23 2012, 08:19) *
Что касается глубины стека - это вам виднее, мы не знаем сложность вашей программы и её требования к стеку.

Я про это:

Go to the top of the page
 
+Quote Post
_Артём_
сообщение Nov 23 2012, 13:50
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 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) {
    
    }
}
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Nov 23 2012, 14:04
Сообщение #11


неотягощённый злом
******

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



Цитата(_Артём_ @ Nov 23 2012, 17:50) *
Чушь какая-то: приоритеты, флаги...
Да нет. Всё верно ему сказали. Можно как вы запрещать собственное прерывание, а можно сбрасывать флаг на запрос прерывания и тот и другой подход решает задачу с мелкими нюансами.
2ТС: А чтобы узнать требуемую глубину стека подход Артёма действительно вам поможет: для начала задайте стек поглубже, заполните его чем-то определённым, запустите программу и проконтролируйте как глубоко она копалась в стеке остановив отладчик через какое-то время (если нет отладчика, то можете в uart выплюнуть стек и увидеть его в терминалке).


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Nov 23 2012, 14:11
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(demiurg_spb @ Nov 23 2012, 16:04) *
Да нет. Всё верно ему сказали.

Ну не всё верно:

Цитата
Только вначале нужно сбросить флаг предыдущего прерывания, т.к. аппаратно он сбрасывается только командой RETI

Аппаратно флаги сбрасываются (не все наверное) при переходе на вектор, а не при выполнении RETI.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 3rd August 2025 - 03:20
Рейтинг@Mail.ru


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