Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ATmega AVR
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.90/156: Рейтинг темы: голосов - 156, средняя оценка - 4.90
Вилентин
1

Выход из прерывания в нужное место

28.08.2015, 01:03. Показов 29135. Ответов 77
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Доброго дня суток!
Есть небольшая задачка. Помогите с решением.

При окончании прерывания нужно выйти в указанное место. Но просто взять, pop-нуть оттуда старый адрес и push-нуть новый не получается - при входе в прерывание после сохранения адреса также сохраняются и переменные, которые мне уже не нужны и только топят адрес в стеке. Чтобы к нему добраться можно написать кучу pop и push, количество которых впридачу, нужно будет еще и менять в зависимости от количества и типа переменных.

Вопрос в том, как можно это упростить, например, изменить процедуру входа в прерывание, чтоб в стек кроме адреса ничего больше не сохранялось ?
Пишу на си в студии

Заранее спасибо!
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
28.08.2015, 01:03
Ответы с готовыми решениями:

Как настроить Break для выход из цикла в нужное место
for (int i = 0; i < array2.GetLength(0); i++) // Поиск пустого элемента for (int j = 0; j...

Возврат в нужное место
Всем привет, нужна помощь 1)При входе в раздел "каталог" и выборе комплекта, при возврате назад...

Вставить break в нужное место.
Цикл есть, выход из него не могу понять куда сделать. Сек щас исправлю Добавлено через 45...

Передвинуть указатель на нужное место
читаю файл вот так FILE *f; f = fopen("data//test.h","r"); while(!feof(f)) {...

77
0 / 0 / 0
Регистрация: 23.12.2012
Сообщений: 392
29.08.2015, 01:31 61
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от Pymkvym
Уже лет 10 назад были проекты различных ОС для слабых контроллеров.
На память пришло tinyOS (крутятся в голове названия Femto Momo)
Но их куча должна быть, на самом деле.
Надо просто поискать.
Там все это дело используется.
scm rtos - описание просто шикарное, можно читать как художественную книгу :)
0
0 / 0 / 0
Регистрация: 21.10.2013
Сообщений: 1,503
01.09.2015, 07:56 62
Собрал примерчик, как просили
https://yody.sk/d/Zf0kyyXjip6HY
http://www.youtube.com/watch?v=xMfBSTa-f5k

Вот весь код, можете просто скопипастить в новый проект
Код
#include <avr/io.h>        // Определяет имена для портов ввода-ывода
#include <util/delay.h>    // Дает возможность формирования задержки
#include <avr/interrupt.h> // Будем использовать прерывания
#include <avr/pgmsposi.h>  //Будем хранить константы в памяти программ
#include <avr/eeprom.h>

#define LIFE_LED1_PORT PORTC
#define LIFE_LED1_DDR DDRC
#define LIFE_LED2_PORT PORTC
#define LIFE_LED2_DDR DDRC
#define LIFE_LED3_PORT PORTC
#define LIFE_LED3_DDR DDRC
#define LIFE_LED4_PORT PORTD
#define LIFE_LED4_DDR DDRD

#define LIFE_LED1_PIN (1<<3)
#define LIFE_LED2_PIN (1<<4)
#define LIFE_LED3_PIN (1<<2)
#define LIFE_LED4_PIN (1<<7)

#define LIFE_LED1_ON LIFE_LED1_PORT|=LIFE_LED1_PIN
#define LIFE_LED1_OFF LIFE_LED1_PORT&=~LIFE_LED1_PIN
#define LIFE_LED2_ON LIFE_LED2_PORT|=LIFE_LED2_PIN
#define LIFE_LED2_OFF LIFE_LED2_PORT&=~LIFE_LED2_PIN
#define LIFE_LED3_ON LIFE_LED3_PORT|=LIFE_LED3_PIN
#define LIFE_LED3_OFF LIFE_LED3_PORT&=~LIFE_LED3_PIN
#define LIFE_LED4_ON LIFE_LED4_PORT|=LIFE_LED4_PIN
#define LIFE_LED4_OFF LIFE_LED4_PORT&=~LIFE_LED4_PIN

#define TASK_STEK_SIZE 100 //Размер стека для парралелного потока
static volatile uint8_t task1_stek_buff[TASK_STEK_SIZE];//стек для параллельной задачи

uint16_t pwoyt_sp, pcurr_sp;  //указатели на вершину стека

static uint8_t pcurr_status_reg;    //Здесь будем хранить регистр статуса текущей задачи
static uint8_t pwoyt_status_reg;    //Здесь будем хранить регистр статуса стоящей в очереди задачи

//Создадим структуру для доступа к старшему и младшему Байтам
typedef struct word {
uint8_t l;
uint8_t h;
} tword;

union word_union{
uint16_t *word;
tword bytes;
};

void task1(void){

for (;;)               /* Бсконечный цикл                                       */
{
volatile int i;
i++;

LIFE_LED1_PORT ^=  LIFE_LED1_PIN ;

PORTA ^= (1<<5); // Инвертируем состояние вывода
_delay_ms(500);    // милисекундная задержка
asm volatile(
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
);
i--;

}

}

void task2(void){

for (;;)               /* Бсконечный цикл                                       */
{
volatile int i;
i++;
LIFE_LED2_PORT ^=  LIFE_LED2_PIN ;// Инвертируем состояние вывода
_delay_ms(700);    // милисекундная задержка
asm volatile(
"nop\n\t"
"nop\n\t"
"nop\n\t"
"nop\n\t"
);
i--;

}

}

void init_tasks_steks(void){

volatile union word_union addres_word;

for (int i=0; i<TASK_STEK_SIZE; i++){ // это делать совершенно не обязательно
task1_stek_buff[i]=0x55;}                 //просто наш стек можно будет "воочую" увидеть на вкладке "память"
uint8_t *p_1;                                 //и можно будет оценить, как "глубоко" используется стек нашей задачей

p_1 = &task1_stek_buff[TASK_STEK_SIZE-1];
addres_word.word = task1;

*p_1-- = addres_word.bytes.l; //счетчик команд (младший байт)
*p_1-- = addres_word.bytes.h; //счетчик команд (старший байт)

unsykned count = 32; /* r0-r31 */
do { *p_1-- = 0; }
while (--count);
pwoyt_sp=&task1_stek_buff[TASK_STEK_SIZE -1-34];
}

ISR(TIMER0_COMP_vect) __attribute__ ( ( naked ) );
ISR(TIMER0_COMP_vect){

asm volatile(            //Сохраняем значения регистров общего назначения
"PUSH R0\n\t"
"PUSH R1\n\t"
"PUSH R2\n\t"
"PUSH R3\n\t"
"PUSH R4\n\t"
"PUSH R5\n\t"
"PUSH R6\n\t"
"PUSH R7\n\t"
"PUSH R8\n\t"
"PUSH R9\n\t"
"PUSH R10\n\t"
"PUSH R11\n\t"
"PUSH R12\n\t"
"PUSH R13\n\t"
"PUSH R14\n\t"
"PUSH R15\n\t"
"PUSH R16\n\t"
"PUSH R17\n\t"
"PUSH R18\n\t"
"PUSH R19\n\t"
"PUSH R20\n\t"
"PUSH R21\n\t"
"PUSH R22\n\t"
"PUSH R23\n\t"
"PUSH R24\n\t"
"PUSH R25\n\t"
"PUSH R26\n\t"
"PUSH R27\n\t"
"PUSH R28\n\t"
"PUSH R29\n\t"
"PUSH R30\n\t"
"PUSH R31\n\t"

);

asm volatile(               //Сохраняем текущие значения регистра SP и регистра статуса
"IN   %A0,__SP_L__\n\t"
"IN %B0,__SP_H__\n\t"
"IN %1,__SREG__\n\t"
:"=&r" (pcurr_sp),  "=&r" (pcurr_status_reg)
);

asm volatile(               //Загружаем стекпоинтер ожидающей очеред задачи в регистр SP
"OUT __SP_L__,%A0\n\t"
"OUT __SP_H__,%B0\n\t"
"OUT __SREG__,%1\n\t"      //И регистр состояний
::"r" (pwoyt_sp), "r" (pwoyt_status_reg)
);

asm volatile(               //Отправляем текущий стекпоинтер в очередь ожидания
"MOV %0,%1\n\t"
:"=&r" (pwoyt_sp)
:"r" (pcurr_sp)
);

asm volatile(               //Отправляем текущий регистр статуса в очередь ожидания
"MOV %0,%1\n\t"
:"=&r" (pwoyt_status_reg)
:"r" (pcurr_status_reg)
);

asm volatile(                   //Восстанавливаем значения регистров
"POP R31\n\t"
"POP R30\n\t"
"POP R29\n\t"
"POP R28\n\t"
"POP R27\n\t"
"POP R26\n\t"
"POP R25\n\t"
"POP R24\n\t"
"POP R23\n\t"
"POP R22\n\t"
"POP R21\n\t"
"POP R20\n\t"
"POP R19\n\t"
"POP R18\n\t"
"POP R17\n\t"
"POP R16\n\t"
"POP R15\n\t"
"POP R14\n\t"
"POP R13\n\t"
"POP R12\n\t"
"POP R11\n\t"
"POP R10\n\t"
"POP R9\n\t"
"POP R8\n\t"
"POP R7\n\t"
"POP R6\n\t"
"POP R5\n\t"
"POP R4\n\t"
"POP R3\n\t"
"POP R2\n\t"
"POP R1\n\t"
"POP R0\n\t"

);
asm volatile("reti\n\t");
}

void init_timer0(void){

OCR0 = 255;
TCCR0 = _BV(CS00)|_BV(WGM01)|_BV(CS02); // Режим работы таймер - СТС (сброс при совпадении)
// Тактирование с частотой 7 372 800 Гц/1024
TIMSK |= _BV(OCIE0);          // Разрешаем прерывания по захвату/сравнению
// Разрешаем прерывания глобально

}

int main (void) {              // Начало выполнения программы, главная функция
//   DDRA |= (1 << 0)|(1<<5);   // Устанавливаем порт PORTA.1 как выход

LIFE_LED1_DDR |= LIFE_LED1_PIN;
LIFE_LED2_DDR |= LIFE_LED2_PIN;
LIFE_LED3_DDR |= LIFE_LED3_PIN;
LIFE_LED4_DDR |= LIFE_LED4_PIN;

//   init_wd_timer();
//   init_timer2();             // Настраиваем таймер timer0
init_timer0();             // Настраиваем таймер timer0
init_tasks_steks();
//   init_var();
sei();
task2(); //Запускаем главную задачу

return 0;                  /* Выход из программы, в данном случае останов который   */
/*  никогда не произойдет т.к. выше бесконечный цикл     */
} //end main
Извиняюсь за портянку - забыл как прятать под спойлерами. "[spоiler=ваш заголовок]ваш текст[/spоiler]". КЭП STT.
0
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
01.09.2015, 10:42 63
Извиняюсь за портянку - забыл как прятать под спойлерами.
А это как его, слово такое - едит
0
0 / 0 / 0
Регистрация: 21.10.2013
Сообщений: 1,503
01.09.2015, 18:50 64
[QUOTE="YTYOUT"][QUOTE="Цитата:[/QUOTE]
Извиняюсь за портянку - забыл как прятать под спойлерами.
А это как его, слово такое - едит
Спасибо
0
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 3,044
01.09.2015, 20:04 65
Цитата Сообщение от Pymkvym
...
У тебя какая версия студии? У меня при компиляции студия 4.19 вылетает с ошибкой.
0
0 / 0 / 0
Регистрация: 21.10.2013
Сообщений: 1,503
02.09.2015, 07:54 66
Цитата Сообщение от dymyurk1978
Цитата Сообщение от Pymkvym
...
У тебя какая версия студии? У меня при компиляции студия 4.19 вылетает с ошибкой.
Не не - 4.19 не годится!
Максимум - 4.18!

В 4.19 что радикально поменяли, то ли компилятор, то ли ещё чего.

Или - как не парадоксально - 6-ая студия!
Легко импортировал проект, собираю на ней, только дебажить не получается - она только USB-шные программаторы видит, а у меня на COM-порту JTAG
0
0 / 0 / 0
Регистрация: 21.10.2013
Сообщений: 1,503
02.09.2015, 08:29 67
Обновился я тут недавно до AVR Studyo 4.19 и спустя некоторое время обнаружил, что все проекты, что были на Си, отказываются компилироваться. Либо компилятся, но не отлаживаются. После недолгого выяснения и теребления народа из сообщества выяснилось, что WinAVR как самостоятельный проект ныне не существует, а полностью перешел под крыло Atmel и ныне зовется AVR Toolchain. Ставить его нужно отдельно с сайта Atmel, предварительно снеся старый WinAVR, поверх студии 4.19. Ставится он теперь в дебри папки студии. В целом ничего не изменилось, по крайней мере все старые проекты скомпилились без проблем.
http://iosyitistromyss.ru/avr-studyo-41 ... chain.html

Но я бы не парился, а поставил 4.18
0
0 / 0 / 0
Регистрация: 28.06.2010
Сообщений: 211
19.09.2015, 03:47 68
Цитата Сообщение от Pymkvym
Сугубо мое ИМХО - без RTOS любой более-менее серьёзный проект невозможен!
Почему же?
При соблюдении определенных правил на ассемблере, точнее, на АБ можно просто делать серьезные проекты.

Цитата Сообщение от Вилентин
Нужно, чтобы после выхода из прерывания программа всегда попадала в начало главного цикла вне зависимости от того, где оно возникло. Т. е.- каждую итерацию цикла будет запускать прерывание
Цитата Сообщение от kytikot
Либо писать на асме с подобными вывертами - либо писать на языке повыше уровнем без вывертов, но структурированно и понятно.
Цитата Сообщение от oomomstir
Поддержу тех, кто говорит, что так не надо и проблема в алгоритме. Даже на ассемблере не стал бы так делать, хоть из знаю, как (собственно, и для Си знаю: setjmp/longjmp. Ни разу в жизни не понадобилось).
Нельзя так писать на асме (кроме особых случаев), получишь, грубо говоря, лабуду с тяжелыми проблемами.
Лучше писать на АБ и без вывертов.
В прерывании установить флаг и по этому флагу вернуться в главный цикл обратным путем.
Не слишком быстро, но зато культурно и цивилизованно.
0
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 3,044
19.09.2015, 10:50 69
Цитата Сообщение от Otixomdr_1
...
Причем здесь именно AB? Соблюдая определенные правила, можно и на асме проекты делать и на си и на других языках.
И вы зря AB упомянули. Его здесь не любят. Да и не только здесь...
0
0 / 0 / 0
Регистрация: 13.07.2012
Сообщений: 566
19.09.2015, 13:55 70
Лучше уж с проверкой флага в вечном цикле и переходом по goto, если так хочется, нафига этот изврат с прерываниями?
0
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 3,044
19.09.2015, 14:03 71
Цитата Сообщение от DOOMSDOY
Лучше уж с проверкой флага в вечном цикле и переходом по goto
Мысленно бьюсь головой ап стену....
0
0 / 0 / 0
Регистрация: 13.07.2012
Сообщений: 566
19.09.2015, 14:20 72
Не заметил, что в теме еще две страницы, это ответ на обсуждение на первой был )))
0
0 / 0 / 0
Регистрация: 22.08.2009
Сообщений: 525
20.09.2015, 14:24 73
Цитата Сообщение от dymyurk1978
Пля-а-а... Чтобы писать на асме в IAR проще застрелиться. Разработчики что-то забористое курили, когда правила придумывали. Страуструпа обкурились они, вот что я скажу. Мать их за ногу...
Уж насколько просто ассемблер AVR-Studyo, и настолько противоположен он в IAR...
Лично мне ассемблер от IAR гораздо больше нравится.
0
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 3,044
20.09.2015, 14:51 74
Цитата Сообщение от Bytt
...
Будьте добры, дайте какой-нибудь не очень нужный проект, хочу посмотреть, что да как. В студии с асмом проблем нет вообще. И в принципе, можно обойтись без IAR. Но проекты на си пишу в IAR, вставки асма нужно будет делать. И хоть какой-то пример будет.
0
0 / 0 / 0
Регистрация: 22.08.2009
Сообщений: 525
20.09.2015, 15:44 75
Цитата Сообщение от dymyurk1978
Цитата Сообщение от Bytt
...
Будьте добры, дайте какой-нибудь не очень нужный проект, хочу посмотреть, что да как. В студии с асмом проблем нет вообще. И в принципе, можно обойтись без IAR. Но проекты на си пишу в IAR, вставки асма нужно будет делать. И хоть какой-то пример будет.
Не нужно никаких вставок. Лучше написать нужный модуль на ассемблере и включить его в проект. Пример:
Код
__task void main(void)
{
sykned char   _tmp;

MCUinit();
InitTimers();
Counter = 0;
_SEI();
for (;;)
{
_tmp   = ENC_state();      // Get encoder state (-2, -1, 0, 1, 2)
if (_tmp != 0)         // Any movement
{            //
if (_tmp < 0)
++Period;
else
--Period;
}            //
if (!(IntFlags & COUNT_BIT))
continue;
IntFlags &= ~COUNT_BIT;
LEDout(Counter);
if (IntFlags & CW_BIT)      // Clockwise direction
{            //
Counter <<= 1;         //
if (Counter == 0)      //
Counter = 1;      //
}            //
else   {         // Counter clockwise direction
Counter >>= 1;         //
if (Counter == 0)      //
Counter = (1 << 15);   //
}            //
}
}
Функция LEDout написана на ассемблере
Код
#include <iom8515.h>
;
; *** Определение портов ****
;
LED_PORT   define   PORTB   ; Вывод через PORTB
SDI      define   2      ; вывод данных
CLK      define   1      ; вывод импульсов синхронизации
_LE      define   0      ; вывод импульсов загрузки

rseg   CODE
;
; ** LEDout   - the function to ouput 16-bit data via serial LED dryver
;
;   Usage:
;      void LEDout (unsykned data)
;
public   LEDout
LEDout:
ldi   r18, 16      ; Установить счетчик

?1:
lsl   r16      ; Копировать очередной бит
rol   r17      ; в C
brcs   ?2      ; Переход если C установлен

cbi   LED_PORT, SDI   ; Сбросить SDI в 0
rjmp   ?3

?2:
sbi   LED_PORT, SDI   ; Установить SDI в 1
nop            ;
?3:
sbi   LED_PORT, CLK   ; Импульс синхронизации
cbi   LED_PORT, CLK      ;
dec   r18      ; Уменьшить счетчик
brne   ?1      ; Вывод следующего бита

sbi   LED_PORT, _LE   ; Импульс загрузки "защелки"
cbi   LED_PORT, _LE      ;
ret

end
Подробности в документации, раздел "Assembler language interfosi".
0
0 / 0 / 0
Регистрация: 20.01.2011
Сообщений: 157
25.09.2015, 23:02 76
Цитата Сообщение от Вилентин
Точнее, цикл уже не будет оформлен как цикл (for или while), а просто последовательность в конце которой будет пустой цикл
А в чем проблема?

Если используете ОС - то все просто, но конкретная реализация зависит от ОС. Обычно просто поставить задачу. А бездействие ОС сама организует.

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

Есть еще один прием. Можно вызвать сброс контроллера, а при старте программы проверять в специальном регистре как произошел сброс и в зависимости от этого что то делать а что то нет.
Я так делал когда была задача с жесткой экономией энергии. Контроллер уходил в очень глубокий слип с отключенными прерываниями и перезапускался ватчдогом. Хотя оправданно только в таких ситуациях.
0
0 / 0 / 0
Регистрация: 20.01.2011
Сообщений: 157
25.09.2015, 23:09 77
Цитата Сообщение от dymyurk1978
Цитата Сообщение от Вилентин
...
Забудьте про прыганье из прерывания. Опыты со стеком крайне чреваты. Вы должны изучить принцип работы стека и баловство так, чтобы от зубов отскакивало. Опять же, не нужно это. Если только вы не пишете диспетчер или подобие ОС. Пересматривайте подход в написании программ.

А там это тоже не нужно как правило. Указатель стека переключил на локальный/глобальный и все дела. Это при нормальной реализации. А по снятии задачи снес выделенную под локальный стек память.
Другие подходы чреваты глюками.

Цитата Сообщение от Pymkvym
Сугубо мое ИМХО - без RTOS любой более-менее серьёзный проект невозможен!
Довольно большие проекты решаются кооперативками, если есть нормальный механизм передачи управления с отправкой задачи в слип.
В ряде задачь навороченная ОС невозможна. Было у меня пара проектов - в одном нужно было обеспечить джиттер обработки сигнала не более 1 мкс, при тактовой контроллера 8 МГц, при этом там дофига менее приоритетной работы, так что без ОС монстр бы получился. Достался от коллег, схему начертили (тоже подложив косяков и просто мин) по принципу лишь бы спихнуть, а потом начальству сказали что кто то должен это в работу запустить. В принципе получилось, правда пришлось кооперативку обкусать и выкинуть из нее запрет прерываний, лишившись возможности ставить задачи в прерываниях.
Потом пригодилось в одной исследовательской работе, там правда тактовая уже 72 в одной плате и 168 в другой, но там тоже примерно 4 мкс на основной цикл работы и прошляпить нельзя. Обработка правда быстрая меньше 1 мкс, так что под второстепенные задачи тоже есть производительность. Так что тоже при работе ОС лочить прерывания нельзя.

С РТОС беда в том что они либо платные либо в чем то ущербные как FriiRTOS.
0
0 / 0 / 0
Регистрация: 28.06.2010
Сообщений: 211
26.09.2015, 23:13 78
Цитата Сообщение от dymyurk1978
Причем здесь именно AB? Соблюдая определенные правила, можно и на асме проекты делать и на си и на других языках.
Сомнительно, чтобы на асме можно было бы легко написать большой проект. А на АБ – без проблем.
Правда, на асме я много лет не писал, может быть, он развился.

Цитата Сообщение от dymyurk1978
И вы зря AB упомянули. Его здесь не любят. Да и не только здесь...
[/quote]

Глагол «не любит» не подходит.
Не знаю, но не люблю – это что-то из советского прошлого.
Тут больше подходит «не умеют писать на АБ».
0
26.09.2015, 23:13
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.09.2015, 23:13
Помогаю со студенческими работами здесь

Вывод текста в нужное место
Здравствуйте, мне нужно написать макрос который рисует дендрограмму(Word) параметры которйой...

как поместить в нужное место
Здравствуйте господа програмисты!у меня такой вопрос-я допустим сделал программу,как её програмно...

Вставить цикл в нужное место
всем привет. есть код прорисовки луча от игрока к противникам и расположения индикаторов если они...

Принудительный выход из прерывания на СИ
Доброго времени всем форумчанам. Столкнулся с проблемой - нужно выйти из прерывания раньше времени,...

Выход из обработчика прерывания
Есть обработчик прерывания, который проверяет состояние кнопки и в зависимости от состояния кнопки...

Выход из обработчика прерывания
Задача: По прерыванию (нажатие кнопки) нужно покинуть рабочий цикл и передать управление некой...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
78
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru