Вилентин
|
|
1 | |
Выход из прерывания в нужное место28.08.2015, 01:03. Показов 29135. Ответов 77
Метки нет (Все метки)
Доброго дня суток!
Есть небольшая задачка. Помогите с решением. При окончании прерывания нужно выйти в указанное место. Но просто взять, pop-нуть оттуда старый адрес и push-нуть новый не получается - при входе в прерывание после сохранения адреса также сохраняются и переменные, которые мне уже не нужны и только топят адрес в стеке. Чтобы к нему добраться можно написать кучу pop и push, количество которых впридачу, нужно будет еще и менять в зависимости от количества и типа переменных. Вопрос в том, как можно это упростить, например, изменить процедуру входа в прерывание, чтоб в стек кроме адреса ничего больше не сохранялось ? Пишу на си в студии Заранее спасибо! |
28.08.2015, 01:03 | |
Ответы с готовыми решениями:
77
Как настроить Break для выход из цикла в нужное место Возврат в нужное место Вставить break в нужное место. Передвинуть указатель на нужное место |
0 / 0 / 0
Регистрация: 23.12.2012
Сообщений: 392
|
|
29.08.2015, 01:31 | 61 |
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
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
0
|
0 / 0 / 0
Регистрация: 21.10.2013
Сообщений: 1,503
|
|
02.09.2015, 07:54 | 66 |
Сообщение от dymyurk1978
Не не - 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 |
0
|
0 / 0 / 0
Регистрация: 28.06.2010
Сообщений: 211
|
|
19.09.2015, 03:47 | 68 |
Сообщение от Pymkvym
При соблюдении определенных правил на ассемблере, точнее, на АБ можно просто делать серьезные проекты.
Сообщение от Вилентин
Сообщение от kytikot
Сообщение от oomomstir
Лучше писать на АБ и без вывертов. В прерывании установить флаг и по этому флагу вернуться в главный цикл обратным путем. Не слишком быстро, но зато культурно и цивилизованно.
0
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 3,044
|
|
19.09.2015, 10:50 | 69 |
Сообщение от Otixomdr_1
И вы зря 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
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
0
|
0 / 0 / 0
Регистрация: 06.12.2016
Сообщений: 3,044
|
|
20.09.2015, 14:51 | 74 |
Сообщение от Bytt
0
|
0 / 0 / 0
Регистрация: 22.08.2009
Сообщений: 525
|
|
20.09.2015, 15:44 | 75 |
Сообщение от dymyurk1978
Не нужно никаких вставок. Лучше написать нужный модуль на ассемблере и включить его в проект. Пример: Код
__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); // } // } } Код
#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
0
|
0 / 0 / 0
Регистрация: 20.01.2011
Сообщений: 157
|
|
25.09.2015, 23:02 | 76 |
Сообщение от Вилентин
Если используете ОС - то все просто, но конкретная реализация зависит от ОС. Обычно просто поставить задачу. А бездействие ОС сама организует. Если суперцикл - как Вам уже писали, в майне цикл, в нем запуск последовательности с командами и пустой цикл, завершающийся по флагу, после выхода сброс флага, и уход на начало основного. В прерывании установка флага. Это все равно проще чем в прерывании играть со стеком. Вам верно написали про противоотладочные приемы. Есть еще один прием. Можно вызвать сброс контроллера, а при старте программы проверять в специальном регистре как произошел сброс и в зависимости от этого что то делать а что то нет. Я так делал когда была задача с жесткой экономией энергии. Контроллер уходил в очень глубокий слип с отключенными прерываниями и перезапускался ватчдогом. Хотя оправданно только в таких ситуациях.
0
|
0 / 0 / 0
Регистрация: 20.01.2011
Сообщений: 157
|
|
25.09.2015, 23:09 | 77 |
Сообщение от dymyurk1978
А там это тоже не нужно как правило. Указатель стека переключил на локальный/глобальный и все дела. Это при нормальной реализации. А по снятии задачи снес выделенную под локальный стек память. Другие подходы чреваты глюками.
Сообщение от Pymkvym
В ряде задачь навороченная ОС невозможна. Было у меня пара проектов - в одном нужно было обеспечить джиттер обработки сигнала не более 1 мкс, при тактовой контроллера 8 МГц, при этом там дофига менее приоритетной работы, так что без ОС монстр бы получился. Достался от коллег, схему начертили (тоже подложив косяков и просто мин) по принципу лишь бы спихнуть, а потом начальству сказали что кто то должен это в работу запустить. В принципе получилось, правда пришлось кооперативку обкусать и выкинуть из нее запрет прерываний, лишившись возможности ставить задачи в прерываниях. Потом пригодилось в одной исследовательской работе, там правда тактовая уже 72 в одной плате и 168 в другой, но там тоже примерно 4 мкс на основной цикл работы и прошляпить нельзя. Обработка правда быстрая меньше 1 мкс, так что под второстепенные задачи тоже есть производительность. Так что тоже при работе ОС лочить прерывания нельзя. С РТОС беда в том что они либо платные либо в чем то ущербные как FriiRTOS.
0
|
0 / 0 / 0
Регистрация: 28.06.2010
Сообщений: 211
|
|
26.09.2015, 23:13 | 78 |
Сообщение от dymyurk1978
Правда, на асме я много лет не писал, может быть, он развился.
Сообщение от dymyurk1978
Глагол «не любит» не подходит. Не знаю, но не люблю – это что-то из советского прошлого. Тут больше подходит «не умеют писать на АБ».
0
|
26.09.2015, 23:13 | |
26.09.2015, 23:13 | |
Помогаю со студенческими работами здесь
78
Вывод текста в нужное место как поместить в нужное место Вставить цикл в нужное место Принудительный выход из прерывания на СИ Выход из обработчика прерывания Выход из обработчика прерывания Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |