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

 
 
> Замена обработчика прерывания в WinAVR
PhX
сообщение Dec 16 2008, 04:23
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 473
Регистрация: 10-09-06
Из: Тольятти. Самарская обл.
Пользователь №: 20 249



Нужно использовать различные обработчики прерывания в зависимости от случая. Например в начале программы
обработчик_пр = функция 1
Код
ISR(INT1_vect)
{
обработчик_пр
}

а затем где-то по далее необходимо заменить его на
обработчик_пр = функция 2
Как это грамотно сделать в WinAVR?


--------------------
Если все, то не я...
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
733259
сообщение Dec 17 2008, 02:01
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 205
Регистрация: 8-03-05
Пользователь №: 3 146



Цитата
Справедливости ради, такой подход имеет один побочный эфект, прерывания будут разрешены еще до окончательного выхода из нашего главного обработчика
С __attribute__((interrupt)) прерывания будут разрешены сразу после входа в INT0_vect (INT0_vect), первой командой будет sei. C __attribute__((signal)) такого не будет, ИМХО правильнее __attribute__((signal,used)). К тому же вариант singlskv не универсален - переключаются векторы INT0, INT1, а если они нужны? В случае "просто" функций - компилятор выдаст предупреждение "misspelled interrupt handler" - из-за этого данный вариант мне показался не подходящим.
ИМХО в реале накладные расходы на if будут меньше push r30, icall и т.д.
Цитата
Как приятно иногда сказать: знатоки, блин.
Не совсем понял иронию.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Dec 17 2008, 10:17
Сообщение #3


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(733259 @ Dec 17 2008, 06:01) *
правильнее __attribute__((signal,used)). К тому же вариант singlskv не универсален - переключаются векторы INT0, INT1, а если они нужны?

Следовательно, как компромисс, можно просто заюзать все неиспользуемые вектора.
Есть у меня еще в стадии тестирования субвекторизация. Допустим, у нас есть функция, при должном внимании к построению которой можно добиться, что она состоит из набора независимых блоков, между которыми компилятор не будет осуществлять операции по сохранению используемых регистров
Код
void foo(void)
{
{
   block 1
}
//........
{
   block N
}
}


Сделаем необходимый инструментарий
Код
typedef uint16_t pc_type; // пока обошел указатели стороной

uint8_t wherePC(void* pcreg) __attribute__((naked));
void setPC(pc_type newPC) __attribute__((naked));
/*Обертка для субвекторов*/
#define SubVector(t_name) if(wherePC(&t_name))


WherePC заточено таким образом, чтобы возвращать 0 при вызове, а в параметре - адрес, с которого ее вызывали, исключая обработку возвращаемого значения.
Код
void setPC(pc_type newPC)
{
asm volatile("ijmp" : : "z" (newPC));
}

uint8_t wherePC(void* pcreg)                      
{
asm volatile (
          "pop        r25"    "\n\t"
        "pop        r24"    "\n\t"
        "adiw    r24,2"    "\n\t"
        "st        Z,    r24"    "\n\t"
        "std    Z+1,r25"    "\n\t"
        "movw    r30,r24"    "\n\t"
        "sbiw    r30,2"    "\n\t"
        "clr r24"    "\n\t"
        "ijmp"                "\n\t"
    ::"z" (pcreg));
}


Используя SubVector(имя_переменной_указателя_на_блок)
Код
void foo(void)
{
static pc_type sv[3];
static uint8_t work = 0;
if(work)
{// код, использующий косв. переход на sv[n]
  set_PC(sv[1]);
}
else
{
  SubVector(sv[0])
  {
    block 1
  }
  SubVector(sv[1])
  {
    block 2
  }
  SubVector(sv[2])
  {
   block 3
  }
  work = 1;
}
return;
}


В итоге при первом вызове получаем адреса блоков кода в переменных sv[], но сами блоки не выполняем, по аналогии с setjmp, а при последующих вызовах - переходим в кратчайшие сроки к независимому блоку. В данном контексте это должно обеспечить выигрыш по сравнению со switch()

Просьба потестить эти примитивы и высказать мнения о применимости. Заранее спасибо.
Go to the top of the page
 
+Quote Post
ReAl
сообщение Dec 20 2008, 16:00
Сообщение #4


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(_Pasha @ Dec 17 2008, 12:17) *
Есть у меня еще в стадии тестирования субвекторизация.
Есть несколько менее переносимый, зато более эффективный способ. В том смысле, что переписать эту субвекторизацию на другой асм другого процессора+компилятора можно, как можно и посмотреть реализацию структуры jump_buf и сделать переключатель, как у Rst7, привязанный к процессору+компилятору, но переписываемый под любую другую компбинацию. А тут - привязка к конкретному инструменту. Но раз в примере всё равно использован gcc, то... в нём можно взять адрес метки.
Во-первых, при этом можно WherePC сделать макросом, адрес вычисляется линкером:
Код
#define glue2(a,b) a##b
#define WPC_LABEL(a,b) glue2(a,b)

#define WherePC(a) { a = &&WPC_LABEL(WPC,__LINE__); WPC_LABEL(WPC,__LINE__):; }

volatile unsigned char a;

void *p1;
void *p2;

void foo() {
    ++a;
    WherePC(p1);
    ++a;
    WherePC(p2);
    ++a;
}
И результат компиляции:
Код
foo:
    lds r24,a
    subi r24,lo8(-(1))
    sts a,r24
    ldi r24,lo8(gs(.L2))
    ldi r25,hi8(gs(.L2))
    sts (p1)+1,r25
    sts p1,r24
.L2:
    lds r24,a
    subi r24,lo8(-(1))
    sts a,r24
    ldi r24,lo8(gs(.L3))
    ldi r25,hi8(gs(.L3))
    sts (p2)+1,r25
    sts p2,r24
.L3:
    lds r24,a
    subi r24,lo8(-(1))
    sts a,r24
    ret

Во вторых, этот макрос при такой постановке вопроса не нужен вообще:
http://forum.sources.ru/index.php?showtopi...p;#entry1929594

В переводе на AVR-ский язык
Код
ISR(INT0_vect)
{
    static void *next_state = &&start;

    goto *next_state;

  start:
    next_state = &&idle;
    return;

  idle:
    if (PINB & 0x01) {
        PORTB |= 0x80;
        next_state = &&drain;
    }
    return;

  drain:
    if (PINB & 0x02) {
        PORTB &= ~0x80;
        next_state = &&idle;
    }
    return;
}

И результат:
Код
    .text
    .size    foo, .-foo
.global    __vector_1
__vector_1:
    push __zero_reg__
    push __tmp_reg__
    in __tmp_reg__,__SREG__
    push __tmp_reg__
    clr __zero_reg__
    push r24
    push r25
    push r30
    push r31

    lds r30,next_state.1519
    lds r31,(next_state.1519)+1
    ijmp
.L6:
.L13:
    ldi r24,lo8(gs(.L7))
    ldi r25,hi8(gs(.L7))
    sts (next_state.1519)+1,r25
    sts next_state.1519,r24
    rjmp .L12
.L7:
    sbis 35-0x20,0
    rjmp .L12
    sbi 37-0x20,7
    ldi r24,lo8(gs(.L10))
    ldi r25,hi8(gs(.L10))
    sts (next_state.1519)+1,r25
    sts next_state.1519,r24
    rjmp .L12
.L10:
    sbis 35-0x20,1
    rjmp .L12
    cbi 37-0x20,7
    rjmp .L13
.L12:

    pop r31
    pop r30
    pop r25
    pop r24
    pop __tmp_reg__
    out __SREG__,__tmp_reg__
    pop __tmp_reg__
    pop __zero_reg__
    reti

    .data
next_state.1519:
    .word    gs(.L6)


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- PhX   Замена обработчика прерывания в WinAVR   Dec 16 2008, 04:23
- - 733259   ИМХО никак, т.к. в AVR адреса векторов фиксированы...   Dec 16 2008, 04:35
- - MrYuran   Определить указатель на функцию и поставить его в ...   Dec 16 2008, 05:59
|- - PhX   Цитата(MrYuran @ Dec 16 2008, 09:59) Опре...   Dec 16 2008, 06:13
|- - ReAl   Цитата(PhX @ Dec 16 2008, 08:13) Кодint m...   Dec 16 2008, 07:49
|- - PhX   Цитата(ReAl @ Dec 16 2008, 11:49) Оно, ко...   Dec 16 2008, 09:19
|- - defunct   Цитата(PhX @ Dec 16 2008, 11:19) Ну хоть ...   Dec 20 2008, 01:03
- - Qwertty   Вызов функции по указателю внутри обработчика веде...   Dec 16 2008, 08:36
|- - MrYuran   Цитата(Qwertty @ Dec 16 2008, 11:36) Вызо...   Dec 17 2008, 11:34
|- - _Pasha   Цитата(MrYuran @ Dec 17 2008, 15:34) а чт...   Dec 17 2008, 11:46
|- - Сергей Борщ   Цитата(_Pasha @ Dec 17 2008, 13:46) Не, т...   Dec 17 2008, 14:31
- - _Pasha   Векторизация прерываний. Например, int1 Soft_vect...   Dec 16 2008, 09:19
|- - _Pasha   Цитата(_Pasha @ Dec 16 2008, 13:19) Прост...   Dec 16 2008, 09:38
|- - aesok   Цитата(_Pasha @ Dec 16 2008, 12:19) Векто...   Dec 16 2008, 10:23
|- - _Pasha   Цитата(aesok @ Dec 16 2008, 14:23) Компил...   Dec 16 2008, 10:48
|- - _Pasha   Цитата(aesok @ Dec 16 2008, 14:23) Компил...   Dec 16 2008, 18:10
- - 733259   А в своем теле функция никакие регистры не использ...   Dec 16 2008, 11:24
|- - _Pasha   Цитата(733259 @ Dec 16 2008, 15:24) А в с...   Dec 16 2008, 11:38
- - ARV   в некоторых случаях можно делать перезапись вектор...   Dec 16 2008, 17:04
- - singlskv   Господа, Вы занимаетесь просто какой-то х.р..й ......   Dec 16 2008, 18:44
|- - _Pasha   Цитата(singlskv @ Dec 16 2008, 22:44) Гос...   Dec 16 2008, 19:50
|- - singlskv   Цитата(_Pasha @ Dec 16 2008, 22:50) Т.е. ...   Dec 16 2008, 20:03
|- - singlskv   Цитата(_Pasha @ Dec 17 2008, 13:17) Следо...   Dec 17 2008, 11:09
|- - _Pasha   Цитата(ReAl @ Dec 20 2008, 20:00) посмотр...   Dec 20 2008, 16:26
- - Rst7   Не знаю, можно ли все, что я тут напишу, реализова...   Dec 17 2008, 07:42
- - 733259   Что Ваш вариант в 20 тактов, что через icall в 21....   Dec 17 2008, 07:55
- - Rst7   ЦитатаЧто Ваш вариант в 20 тактов, что через icall...   Dec 17 2008, 08:19
- - ReAl   Я погонял компиляцию этого дела в разных режимах. ...   Dec 20 2008, 16:34
- - _Pasha   Цитата(ReAl @ Dec 20 2008, 20:34) что даё...   Dec 20 2008, 16:49


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

 


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


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