Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: MSP, ISR
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
Kaplinsky
Допустим есть процедура обработки прерывания, описана так:

#pragma vector=PORT2_VECTOR
__interrupt void P2_INT_1(){
...
}

и допустим имеется другая:

__interrupt void P2_INT_2(){
...
}

Понятно что первая будет работать так как она зарегистрирована с помощью #pragma vector

А как в процесе выполнения программы (при определенных условиях) перерегистрировать (поменять) ISR на другую (с последующим возвратом первой) ?

На С естественно.

Ветвление внутри единой ISR непредлагать smile.gif
vvvvv
Вообщем можно сделать так :
1. Завести сигнал прерывания, предполагается, что это все таки сигнал сразу
параллельно на два вывода порта 1 или 2.
2. Назначить этим выводам разные процедуры.
3. Все, маскируя тот или иной вывод, мы выбираем нужную процедуру.
Kaplinsky
Цитата(vvvvv @ May 4 2006, 12:38) *
Вообщем можно сделать так :
1. Завести сигнал прерывания, предполагается, что это все таки сигнал сразу
параллельно на два вывода порта 1 или 2.
2. Назначить этим выводам разные процедуры.
3. Все, маскируя тот или иной вывод, мы выбираем нужную процедуру.

некатит. Сигналы заводить это не по теме. Устройство уже готово, его надо програмить.

Грязно материтсо ненада, вектора поменять - с удовольствием, тока как это сделать посредством С ?
Дело в том ,что регистрировать прерывания кроме как #pragma vector я неумею. В хелпе (IARовском) по этому поводу ничего толком ненашел.

Или может кто-нить покажет как это сделать спомощью вставки асемблерной ?
VAI
А если таблица векторов во флэше будет вызывать таблицу векторов в озу.
А в озу Вы налету можете переопределять обработчики. (так когдато в ДОСе веселились)
Гляньте пример во вложении.
dxp
Цитата(Kaplinsky @ May 4 2006, 17:18) *
Грязно материтсо ненада, вектора поменять - с удовольствием, тока как это сделать посредством С ?
Дело в том ,что регистрировать прерывания кроме как #pragma vector я неумею. В хелпе (IARовском) по этому поводу ничего толком ненашел.

Или может кто-нить покажет как это сделать спомощью вставки асемблерной ?

Вектора прерываний в MSP430 лежат во флеши, сами их не поменяешь. Но можно делать дополнительную векторизацию - при прерывании в PC загружается адрес обработчика, а в обработчике просто тупой переход на нужную функцию - jump ...

Хотя все-таки не понятно, что в конечном итоге требуется. Вы бы задачу обрисовали, тогда, может, народ и решение наилучшее подскажет.
Kaplinsky
Цитата(VAI @ May 4 2006, 14:57) *
А в озу Вы налету можете переопределять обработчики. (так когдато в ДОСе веселились)

В ДОСе я бы повеселился примерно так:

OldVec = GetIntVec(PORT2_VECTOR)
SetIntVec(PORT2_VECTOR,@P2_INT_2())

...
SetIntVec(PORT2_VECTOR, OldVec);

Мне же надо сделать подобное под IAR for MSP (забыл уточнить)
Еще я работаю с MSP430F149-й.

Сейчас ISR работает на ветвлении (вначале ISR стоит if который проверяет флаг) но хотелось бы сделать красяво.
ig_z
Цитата(dxp @ May 4 2006, 15:15) *
Хотя все-таки не понятно, что в конечном итоге требуется. Вы бы задачу обрисовали, тогда, может, народ и решение наилучшее подскажет.


Одно из двух
-или пытается смастерить обработчик прерываний как автомат состояний
-или пытается сохранить скорость "Прямой передачи управления" и устранить излишние сохранения-восстановления контекста, как в "Передаче управления на основе программного прерывания" biggrin.gif

По идее в обработчике должна стоять команда косвенного перехода по содержимому ячейки памяти. (Если конечно мсп со своей ортогональной архитектурой поддерживает такое. )
А в теле обработчика менять содержимое этой ячейки памяти на адрес обработчика(ов)-компаньона(ов)
rezident
Цитата(Kaplinsky @ May 4 2006, 19:00) *
Сейчас ISR работает на ветвлении (вначале ISR стоит if который проверяет флаг) но хотелось бы сделать красяво.

VAI, вам уже подсказал способ и дал пример реализации. Выделите в ОЗУ сегмент под перемещаемые вектора прерываний. Сами вектора (те которые во Flash) определите как адреса ячеек ОЗУ в этом сегменте (который в ОЗУ). В качестве перемещаемого вектора используйте команду безусловного перехода (которая опять же в ОЗУ расположена) на подпрограмму обработки ISR. Адрес для перехода вы сможете менять оперативно из самой программы. Все это возможно благодаря ортогональности команд MSP430.
dxp
Цитата(ig_z @ May 4 2006, 20:11) *
-или пытается сохранить скорость "Прямой передачи управления" и устранить излишние сохранения-восстановления контекста, как в "Передаче управления на основе программного прерывания" biggrin.gif

smile.gif

Цитата(ig_z @ May 4 2006, 20:11) *
По идее в обработчике должна стоять команда косвенного перехода по содержимому ячейки памяти.

Вот я выше что-то подобное и предложил. Но...

Цитата(ig_z @ May 4 2006, 20:11) *
(Если конечно мсп со своей ортогональной архитектурой поддерживает такое. )
А в теле обработчика менять содержимое этой ячейки памяти на адрес обработчика(ов)-компаньона(ов)

...Но тут, имхо, трудность в том, что переход надо делать не на любую функцию, а на функцию-обработчик - чтобы компилятор (благодаря __interrupt) понял, что это не простая функция и сохранял используемые ресурсы, как положено в обработчике прерываний. Можно, конечно, наобъявлять функций с квалификатором __interrupt без указания вектора, а потом подставлять их адреса. Но предупреждений он насыпет, что тоже некузяво. Предупреждения можно подавить, но кузявее от этого не становится. sad.gif
VAI
Цитата(Kaplinsky @ May 4 2006, 18:00) *
Цитата(VAI @ May 4 2006, 14:57) *

А в озу Вы налету можете переопределять обработчики. (так когдато в ДОСе веселились)

Мне же надо сделать подобное под IAR for MSP (забыл уточнить)
Еще я работаю с MSP430F149-й.

Сейчас ISR работает на ветвлении (вначале ISR стоит if который проверяет флаг) но хотелось бы сделать красяво.

А Вы пример смотрели? Он под ИАР и для MSP.
Цитата
dxp
Вектора прерываний в MSP430 лежат во флеши, сами их не поменяешь. Но можно делать дополнительную векторизацию - при прерывании в PC загружается адрес обработчика, а в обработчике просто тупой переход на нужную функцию - jump ...

В этом и заключена основная идея. Делаете в ОЗУ массив из указателей на функции __interrupt. На элементы этого массива указывает родная таблица прерываний во флэше. А уж поменять значение элемента массива....

А в досе можно проще
Код
typedef void ( far interrupt *_INTER)( void );
.....
static _INTER far *int_tab = (void far *)NULL;  // таблица векторов прерываний
static void ( interrupt far *old_1c )();
.....
  _disable();                     // Запретим прерывания
  old_1c = int_tab[0x1c];         // Возьмем вектор
  int_tab[0x1c] = new_1c;         // Установим новый
  _enable();                      // Разрешим прерывания
ig_z
Цитата(dxp @ May 4 2006, 16:23) *
...Но тут, имхо, трудность в том, что переход надо делать не на любую функцию, а на функцию-обработчик - чтобы компилятор (благодаря __interrupt) понял, что это не простая функция и сохранял используемые ресурсы, как положено в обработчике прерываний. Можно, конечно, наобъявлять функций с квалификатором __interrupt без указания вектора, а потом подставлять их адреса. Но предупреждений он насыпет, что тоже некузяво. Предупреждения можно подавить, но кузявее от этого не становится. sad.gif


Не удержался и проверил. Ни одного предупреждения. После двух недель безрезультатного траха с иаровской реализацией шаблонов - просто не верится.
condor
Цитата(Kaplinsky @ May 4 2006, 11:14) *
Допустим есть процедура обработки прерывания, описана так:

#pragma vector=PORT2_VECTOR
__interrupt void P2_INT_1(){
...
}

и допустим имеется другая:

__interrupt void P2_INT_2(){
...
}

Понятно что первая будет работать так как она зарегистрирована с помощью #pragma vector

А как в процесе выполнения программы (при определенных условиях) перерегистрировать (поменять) ISR на другую (с последующим возвратом первой) ?

На С естественно.

Ветвление внутри единой ISR непредлагать smile.gif


Я делаю так:
Код
void port2_int_func1 (void)
{
   //Первый обработчик
}

void port2_int_func2 (void)
{
   //Второй обработчик
}

void (*port2_int_handler)(void) = port2_int_func1;

//-----------------------------------
#pragma vector = PORT2_VECTOR
//-----------------------------------
__interrupt void port2_int(void)
{
   (*port2_int_handler)();
}


А дальше port2_int_handler можно присваивать указатель на любую функцию.
И никаких предупреждений.
Правда задержка вызова прерывания увеличивается с 6 до 8 тактов.
dxp
Цитата(ig_z @ May 5 2006, 04:40) *
Цитата(dxp @ May 4 2006, 16:23) *

...Но тут, имхо, трудность в том, что переход надо делать не на любую функцию, а на функцию-обработчик - чтобы компилятор (благодаря __interrupt) понял, что это не простая функция и сохранял используемые ресурсы, как положено в обработчике прерываний. Можно, конечно, наобъявлять функций с квалификатором __interrupt без указания вектора, а потом подставлять их адреса. Но предупреждений он насыпет, что тоже некузяво. Предупреждения можно подавить, но кузявее от этого не становится. sad.gif


Не удержался и проверил. Ни одного предупреждения. После двух недель безрезультатного траха с иаровской реализацией шаблонов - просто не верится.

Дейсвительно, текущая версия (у меня 3.30) под MSP430 молча глотает __interrupt без указания вектора, что, имхо, нехорошо - грабли скрытые. А вот под AVR (4.12) как положено:

Код
> Compile  : "main.cpp"

  __interrupt void Timer1_period_ISR()
                   ^
"D:\slon\2\EWAVR_V4\Src\main.cpp",224  Warning[Ta006]: Interrupt function has no assigned vector.


Т.ч. по-любому способ как минимум не переносимый даже в пределах компиляторов одного производителя. Имхо, выдача предупреждения на отсутствие вектора - есть правильно, т.к. защищает от хоть и несложных, но досадных граблей.

Цитата(condor @ May 5 2006, 06:11) *
Я делаю так:
Код
void port2_int_func1 (void)
{
   //Первый обработчик
}

void port2_int_func2 (void)
{
   //Второй обработчик
}

void (*port2_int_handler)(void) = port2_int_func1;

//-----------------------------------
#pragma vector = PORT2_VECTOR
//-----------------------------------
__interrupt void port2_int(void)
{
   (*port2_int_handler)();
}


А дальше port2_int_handler можно присваивать указатель на любую функцию.
И никаких предупреждений.
Правда задержка вызова прерывания увеличивается с 6 до 8 тактов.

В этом случае получаете дополнительное сохранение части контекста - компилятор будет сохранять все scratch регистры даже если какие-то из них не используются. На MSP430 здесь оверхед небольшой, т.к. таких регистров мало. А вот на других платформах уже не так радостно - на том же AVR сохраняться будет почти половина (из 32) регистров. Т.ч. оверхед по-любому.
Kaplinsky
Цитата(VAI @ May 4 2006, 16:34) *
А Вы пример смотрели? Он под ИАР и для MSP.

Вектора прерываний в MSP430 лежат во флеши, сами их не поменяешь. Но можно делать дополнительную векторизацию - при прерывании в PC загружается адрес обработчика, а в обработчике просто тупой переход на нужную функцию - jump ...

В этом и заключена основная идея. Делаете в ОЗУ массив из указателей на функции __interrupt. На элементы этого массива указывает родная таблица прерываний во флэше. А уж поменять значение элемента массива....

В пример вникся. Мда, толково... наверно реализую. В любом случае a14.gif
Единственное чего недопонял, это как родная таблица из флеша указывает на значения элементов масива ?


Цитата(condor @ May 5 2006, 02:11) *
Я делаю так:
Код
void port2_int_func1 (void)
{
   //Первый обработчик
}

void port2_int_func2 (void)
{
   //Второй обработчик
}

void (*port2_int_handler)(void) = port2_int_func1;

//-----------------------------------
#pragma vector = PORT2_VECTOR
//-----------------------------------
__interrupt void port2_int(void)
{
   (*port2_int_handler)();
}


А дальше port2_int_handler можно присваивать указатель на любую функцию.
И никаких предупреждений.
Правда задержка вызова прерывания увеличивается с 6 до 8 тактов.


Классно, идея неплохая. Но я потому и хочу подменить вектор потому что критично по времени.
VAI
Оба варианта, в принципе одно и тоже, только 2-й вариант - под единственное прерывание, а первый на все.

> как родная таблица из флеша указывает на значения элементов масива
исследуйте файл *.s43 и *.xls из примера
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.