|
|
  |
MSP, ISR, изменение процедуры обработки прерывания |
|
|
|
May 4 2006, 08:14
|

Частый гость
 
Группа: Свой
Сообщений: 97
Регистрация: 26-05-05
Из: Киев, Украина
Пользователь №: 5 426

|
Допустим есть процедура обработки прерывания, описана так: #pragma vector=PORT2_VECTOR __interrupt void P2_INT_ 1(){ ... } и допустим имеется другая: __interrupt void P2_INT_ 2(){ ... } Понятно что первая будет работать так как она зарегистрирована с помощью #pragma vector А как в процесе выполнения программы (при определенных условиях) перерегистрировать (поменять) ISR на другую (с последующим возвратом первой) ? На С естественно. Ветвление внутри единой ISR непредлагать
--------------------
Смотреть в себя, зреть муки свои, зная, что сам ты виновник мук - вот истинное страдание. Отладка / Софокл, "Аякс".
|
|
|
|
|
May 4 2006, 10:18
|

Частый гость
 
Группа: Свой
Сообщений: 97
Регистрация: 26-05-05
Из: Киев, Украина
Пользователь №: 5 426

|
Цитата(vvvvv @ May 4 2006, 12:38)  Вообщем можно сделать так : 1. Завести сигнал прерывания, предполагается, что это все таки сигнал сразу параллельно на два вывода порта 1 или 2. 2. Назначить этим выводам разные процедуры. 3. Все, маскируя тот или иной вывод, мы выбираем нужную процедуру. некатит. Сигналы заводить это не по теме. Устройство уже готово, его надо програмить. Грязно материтсо ненада, вектора поменять - с удовольствием, тока как это сделать посредством С ? Дело в том ,что регистрировать прерывания кроме как #pragma vector я неумею. В хелпе (IARовском) по этому поводу ничего толком ненашел. Или может кто-нить покажет как это сделать спомощью вставки асемблерной ?
--------------------
Смотреть в себя, зреть муки свои, зная, что сам ты виновник мук - вот истинное страдание. Отладка / Софокл, "Аякс".
|
|
|
|
|
May 4 2006, 11:57
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 120
Регистрация: 17-06-04
Пользователь №: 37

|
А если таблица векторов во флэше будет вызывать таблицу векторов в озу. А в озу Вы налету можете переопределять обработчики. (так когдато в ДОСе веселились) Гляньте пример во вложении.
--------------------
Если зайца бить, его можно и спички научить зажигать Сколько дурака не бей - умнее не будет. Зато опытнее
|
|
|
|
|
May 4 2006, 12:15
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(Kaplinsky @ May 4 2006, 17:18)  Грязно материтсо ненада, вектора поменять - с удовольствием, тока как это сделать посредством С ? Дело в том ,что регистрировать прерывания кроме как #pragma vector я неумею. В хелпе (IARовском) по этому поводу ничего толком ненашел.
Или может кто-нить покажет как это сделать спомощью вставки асемблерной ? Вектора прерываний в MSP430 лежат во флеши, сами их не поменяешь. Но можно делать дополнительную векторизацию - при прерывании в PC загружается адрес обработчика, а в обработчике просто тупой переход на нужную функцию - jump ... Хотя все-таки не понятно, что в конечном итоге требуется. Вы бы задачу обрисовали, тогда, может, народ и решение наилучшее подскажет.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
May 4 2006, 13:00
|

Частый гость
 
Группа: Свой
Сообщений: 97
Регистрация: 26-05-05
Из: Киев, Украина
Пользователь №: 5 426

|
Цитата(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 который проверяет флаг) но хотелось бы сделать красяво.
--------------------
Смотреть в себя, зреть муки свои, зная, что сам ты виновник мук - вот истинное страдание. Отладка / Софокл, "Аякс".
|
|
|
|
|
May 4 2006, 13:11
|
Местный
  
Группа: Свой
Сообщений: 437
Регистрация: 27-08-04
Пользователь №: 551

|
Цитата(dxp @ May 4 2006, 15:15)  Хотя все-таки не понятно, что в конечном итоге требуется. Вы бы задачу обрисовали, тогда, может, народ и решение наилучшее подскажет. Одно из двух -или пытается смастерить обработчик прерываний как автомат состояний -или пытается сохранить скорость "Прямой передачи управления" и устранить излишние сохранения-восстановления контекста, как в "Передаче управления на основе программного прерывания" По идее в обработчике должна стоять команда косвенного перехода по содержимому ячейки памяти. (Если конечно мсп со своей ортогональной архитектурой поддерживает такое. ) А в теле обработчика менять содержимое этой ячейки памяти на адрес обработчика(ов)-компаньона(ов)
|
|
|
|
|
May 4 2006, 13:23
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(ig_z @ May 4 2006, 20:11)  -или пытается сохранить скорость "Прямой передачи управления" и устранить излишние сохранения-восстановления контекста, как в "Передаче управления на основе программного прерывания"  Цитата(ig_z @ May 4 2006, 20:11)  По идее в обработчике должна стоять команда косвенного перехода по содержимому ячейки памяти. Вот я выше что-то подобное и предложил. Но... Цитата(ig_z @ May 4 2006, 20:11)  (Если конечно мсп со своей ортогональной архитектурой поддерживает такое. ) А в теле обработчика менять содержимое этой ячейки памяти на адрес обработчика(ов)-компаньона(ов) ...Но тут, имхо, трудность в том, что переход надо делать не на любую функцию, а на функцию-обработчик - чтобы компилятор (благодаря __interrupt) понял, что это не простая функция и сохранял используемые ресурсы, как положено в обработчике прерываний. Можно, конечно, наобъявлять функций с квалификатором __interrupt без указания вектора, а потом подставлять их адреса. Но предупреждений он насыпет, что тоже некузяво. Предупреждения можно подавить, но кузявее от этого не становится.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
May 4 2006, 13:34
|

Профессионал
    
Группа: Модераторы
Сообщений: 1 120
Регистрация: 17-06-04
Пользователь №: 37

|
Цитата(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(); // Разрешим прерывания
--------------------
Если зайца бить, его можно и спички научить зажигать Сколько дурака не бей - умнее не будет. Зато опытнее
|
|
|
|
|
May 4 2006, 21:40
|
Местный
  
Группа: Свой
Сообщений: 437
Регистрация: 27-08-04
Пользователь №: 551

|
Цитата(dxp @ May 4 2006, 16:23)  ...Но тут, имхо, трудность в том, что переход надо делать не на любую функцию, а на функцию-обработчик - чтобы компилятор (благодаря __interrupt) понял, что это не простая функция и сохранял используемые ресурсы, как положено в обработчике прерываний. Можно, конечно, наобъявлять функций с квалификатором __interrupt без указания вектора, а потом подставлять их адреса. Но предупреждений он насыпет, что тоже некузяво. Предупреждения можно подавить, но кузявее от этого не становится.  Не удержался и проверил. Ни одного предупреждения. После двух недель безрезультатного траха с иаровской реализацией шаблонов - просто не верится.
|
|
|
|
|
May 4 2006, 23:11
|

Частый гость
 
Группа: Свой
Сообщений: 93
Регистрация: 18-06-05
Из: Kyiv, Ukraine
Пользователь №: 6 126

|
Цитата(Kaplinsky @ May 4 2006, 11:14)  Допустим есть процедура обработки прерывания, описана так: #pragma vector=PORT2_VECTOR __interrupt void P2_INT_ 1(){ ... } и допустим имеется другая: __interrupt void P2_INT_ 2(){ ... } Понятно что первая будет работать так как она зарегистрирована с помощью #pragma vector А как в процесе выполнения программы (при определенных условиях) перерегистрировать (поменять) ISR на другую (с последующим возвратом первой) ? На С естественно. Ветвление внутри единой ISR непредлагать  Я делаю так: Код 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 тактов.
Сообщение отредактировал condor - May 4 2006, 23:16
|
|
|
|
|
May 5 2006, 04:12
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(ig_z @ May 5 2006, 04:40)  Цитата(dxp @ May 4 2006, 16:23)  ...Но тут, имхо, трудность в том, что переход надо делать не на любую функцию, а на функцию-обработчик - чтобы компилятор (благодаря __interrupt) понял, что это не простая функция и сохранял используемые ресурсы, как положено в обработчике прерываний. Можно, конечно, наобъявлять функций с квалификатором __interrupt без указания вектора, а потом подставлять их адреса. Но предупреждений он насыпет, что тоже некузяво. Предупреждения можно подавить, но кузявее от этого не становится.  Не удержался и проверил. Ни одного предупреждения. После двух недель безрезультатного траха с иаровской реализацией шаблонов - просто не верится. Дейсвительно, текущая версия (у меня 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) регистров. Т.ч. оверхед по-любому.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
May 5 2006, 09:31
|

Частый гость
 
Группа: Свой
Сообщений: 97
Регистрация: 26-05-05
Из: Киев, Украина
Пользователь №: 5 426

|
Цитата(VAI @ May 4 2006, 16:34)  А Вы пример смотрели? Он под ИАР и для MSP.
Вектора прерываний в MSP430 лежат во флеши, сами их не поменяешь. Но можно делать дополнительную векторизацию - при прерывании в PC загружается адрес обработчика, а в обработчике просто тупой переход на нужную функцию - jump ...
В этом и заключена основная идея. Делаете в ОЗУ массив из указателей на функции __interrupt. На элементы этого массива указывает родная таблица прерываний во флэше. А уж поменять значение элемента массива.... В пример вникся. Мда, толково... наверно реализую. В любом случае Единственное чего недопонял, это как родная таблица из флеша указывает на значения элементов масива ? Цитата(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 тактов. Классно, идея неплохая. Но я потому и хочу подменить вектор потому что критично по времени.
--------------------
Смотреть в себя, зреть муки свои, зная, что сам ты виновник мук - вот истинное страдание. Отладка / Софокл, "Аякс".
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|