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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> AVR ATmega32 прерывания
MmX12345
сообщение Jun 14 2011, 11:28
Сообщение #1





Группа: Новичок
Сообщений: 4
Регистрация: 13-03-11
Пользователь №: 63 572



Добрый день.
Подскажите, пожалуйста, как будет вести себя микроконтроллер в вледущей ситуации:

...
+000000A8: 94F8 CLI Global Interrupt Disable - запретить прерывания
(Установка флага прерывания...)
+000000A9: BF9E OUT 0x3E,R25 Out to I/O location - запись старшего байта в указателя стека
+000000AA: BE0F OUT 0x3F,R0 Out to I/O location - восстановить SREG
+000000AB: BF8D OUT 0x3D,R24 Out to I/O location - запись младшего байта в указателя стека
...

Вопрос вот в чем. Какая будет последовательность выполнения команд.
Выполнятся ли все три инструкции до прерывания, или может быть такое, что выполнятся только 2 и затем произойдет переброс в прерывание?

Заранее спасибо.
Go to the top of the page
 
+Quote Post
_guardianangel
сообщение Jun 14 2011, 12:44
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 37
Регистрация: 6-04-10
Из: Ryazan
Пользователь №: 56 444



Всё зависит от того что в R0. Т.е. что было в SREG перед сохранением его в R0. Если флаг IE был сброшен, то ничего не произойдет, если утановлен - то запись млядшего байта успеет произойти - время реакции на прерывание 4 такта.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Jun 14 2011, 18:13
Сообщение #3


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(MmX12345 @ Jun 14 2011, 15:28) *
CLI // запретить прерывания
OUT 0x3E,R25 // запись старшего байта в указателя стека
OUT 0x3F,R0 // восстановить SREG
OUT 0x3D,R24 // запись младшего байта в указателя стека
Вся эта последовательность инструкций выполнится атомарно (при запрещённых прерываниях) в любом случае. Две последние инструкции поменяны местами с целью выиграть время (быстрее разрешить прерывания). Ибо архитектура AVR устроена таким образом, что после разрешения прерываний, даже при активном запросе на прерывание от любой периферии, ядро гарантировано выполнит одну инструкцию до обработки запроса на прерывание. И этой инструкцией в вашем случае будет OUT 0x3D,R24.
Это сделано насколько я понимаю с целью чтобы фоновая программа не зависла вусмерть при каком-то "залипшем" источнике прерываний.

Цитата(_guardianangel @ Jun 14 2011, 16:44) *
Всё зависит от того что в R0.
Ошибаетесь. Никак не зависит от содержимого R0.
Цитата
время реакции на прерывание 4 такта.
Снова ошибаетесь. Время реакции на прерывание никак не связано с вопросом. Пусть хоть 44 такта или 1 такт. Время реакции на прерывание - это то сколько тактов нужно процессору с момента запроса прерывания до начала выполнения обработчика прерывания. И всё это время процессор уже не выполняет фоновую программу как вы подумали, а помещает в стек адрес возврата и совершает переход на вектор прерывания. И только. Хотя мог бы и регистр статуса сохранить аппаратно, да и регистровые пары некоторые, а нет...


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
element
сообщение Sep 21 2011, 13:20
Сообщение #4





Группа: Новичок
Сообщений: 8
Регистрация: 23-01-09
Пользователь №: 43 859



при доступе к CPU_SPL проц аппаратно запрещает прерывания на 4 такта, никаких CLI не нужно. и атомарность тут непричём (stack pointer не имеет никаких временных внутренних регистров, и последовательность SPL/SPH не важна).

для вашего случая достаточно так:

OUT CPU_SPL,R24
OUT CPU_SPH,R25

Читайте внимательно даташит,
раздел 3 AVR CPU, подраздел 3.8 Stack pointer:

To prevent corruption when updating the Stack Pointer from software, a write to SPL will automatically
disable interrupts for up to 4 instructions or until the next I/O memory write.
Go to the top of the page
 
+Quote Post
Палыч
сообщение Sep 21 2011, 15:16
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(element @ Sep 21 2011, 17:20) *
Читайте внимательно даташит

Людей в заблуждение не вводите!
В этом топике речь шла о ATmega32. Вы же привели цитату из документации на xmega...
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Sep 21 2011, 15:42
Сообщение #6


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



QUOTE (Палыч @ Sep 21 2011, 19:16) *
Людей в заблуждение не вводите!
В этом топике речь шла о ATmega32. Вы же привели цитату из документации на xmega...

+1
to element :
Вообщем-то ,в зависимости от модели, mega требуется разное время для перехода в обработчик прерывания MEGA64 - 4 такта, Mega164P - 5
(если только не спать) , но Вы забыли на что оно тратится . В том числе ( и в первую очередь ) на запись в стек PC+1 адрес (адрес возврата в основную программу) ,а в PC - адрес перехода. При этом никаких других инструкций (комманд) не выполняется!! Если логически подумаете , то поймёте почему.
MmX12345
И вообще мне не понятно , что Вы делаете со стеком, зачем Вам менять его вершину в основной программе


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Sep 22 2011, 05:36
Сообщение #7


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(ILYAUL @ Sep 21 2011, 19:42) *
И вообще мне не понятно , что Вы делаете со стеком, зачем Вам менять его вершину в основной программе
А как по вашему стековый фрейм для локальных переменных функции организовывается? (для тех переменных что не влезли в регистры или обращение к которым происходит по указателю). Попробуйте объявить не статический локальный массив байт эдак на 10. И посмотрите что там компилятор нагенерит. А потом добавьте массиву квалификатор static и снова посмотрите.
Видите разницу и в размере программы и в скорости её выполнения?
Поэтому некоторые компиляторы (IAR и ImageCraft например) используют софтовый стек, тем самым выигрывают по накладным расходам, но проигрывают по кол-ву свободных регистров общего пользования.
И вторая мысль: иногда в особо критичных местах выгоднее объявлять статические локальные массивы, даже если они таковыми по идеологии быть не должны...


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Sep 22 2011, 06:04
Сообщение #8


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



QUOTE (demiurg_spb @ Sep 22 2011, 09:36) *
А как по вашему стековый фрейм для локальных переменных функции организовывается? (для тех переменных что не влезли в регистры или обращение к которым происходит по указателю). Попробуйте объявить не статический локальный массив байт эдак на 10. И посмотрите что там компилятор нагенерит. А потом добавьте массиву квалификатор static и снова посмотрите.
Видите разницу и в размере программы и в скорости её выполнения?
Поэтому некоторые компиляторы (IAR и ImageCraft например) используют софтовый стек, тем самым выигрывают по накладным расходам, но проигрывают по кол-ву свободных регистров общего пользования.
И вторая мысль: иногда в особо критичных местах выгоднее объявлять статические локальные массивы, даже если они таковыми по идеологии быть не должны...

Ну это понятно для языков высокого уровня. Но здесь asm , где необходимые данные для сохоанения ты выбираешь сам. И достаточно часто , кроме SREG и регистра temp , в прерываниях сохранять в стеке ничего не нужно


CODE
ADCReady:
        in        SaveSREG,SREG; SREG; Заталкиваем в стек
        push    SaveSREG
        push    temp        
                                lds        temp,ADCH; Считывание только старшего регистра
        add        mean0,temp; Вычисление среднего
        adc        mean1,zero; Вычисление среднего
        sbr        Flags,1<<fl_ADCReady; Устанавливаем флаг готовности среднего значения ADC
        pop        temp
        pop        SaveSREG
        out        SREG,SaveSREG; Выталкиваем из стека
        reti


Хотя и это прерывание можно значительно сократить оставив только

CODE
in        SaveSREG,SREG; SREG; Заталкиваем в стек
sbr        Flags,1<<fl_ADCReady; Устанавливаем флаг ADC
out        SREG,SaveSREG; Выталкиваем из стека


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Sep 22 2011, 06:12
Сообщение #9


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Вы не поняли. Нет разницы Cи или асм.
Нужен временный локальный буфер на 100 байт в процедуре. Ваши действия?
Другой пример: нужно передать в процедуру большую структуру по значению или вернуть структуру опять-же по значению а не по указателю.
Это бывает редко нужно, но всё же встречается.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Sep 22 2011, 06:23
Сообщение #10


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



QUOTE (demiurg_spb @ Sep 22 2011, 10:12) *
Вы не поняли. Нет разницы Cи или асм.
Нужен временный локальный буфер на 100 байт в процедуре. Ваши действия?

Так . Сейчас я для себя пойму задачу:
Я понял так - временный локальный буфер - срочно возникла необходимость сохранить 100 байт в области памяти , при этом заранее в .dseg он не был зарезервирован. И Вы предлагаете перенести вершину стека и просто затолкнуть туда данные? Правильно?


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
MKdemiurg
сообщение Sep 22 2011, 07:12
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 624
Регистрация: 15-06-10
Из: Россия
Пользователь №: 57 939



Чтоб не создавать новую тему спрошу тут( всё равно ТС уже давно пропал)

Что будет если на вход внешнего прерывания( по срезу) прийдут два импульса с разницей в несколько мс( а может и меньше - прерывание от RTS - будильника ичасов) . Одно из прерываний пропадёт ?
Просто непонятно как работать и с часами и с будильником одновременно изза этого.

ЗЫ Забыл дописать контроллер прерыванием выводится из powerdown.

Сообщение отредактировал MKdemiurg - Sep 22 2011, 07:37
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Sep 22 2011, 08:02
Сообщение #12


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(ILYAUL @ Sep 22 2011, 10:23) *
Так . Сейчас я для себя пойму задачу:
Я понял так - временный локальный буфер - срочно возникла необходимость сохранить 100 байт в области памяти , при этом заранее в .dseg он не был зарезервирован. И Вы предлагаете перенести вершину стека и просто затолкнуть туда данные? Правильно?

Именно! Главное при выходе из процедуры отмотать стек обратно! Таким макаром достигается реентерабельность функций в противовес методу:
Цитата
заранее в .dseg ... зарезервирован

Это конечно же не я придумал, а много-много лет назад мужики с бородами до пупаsm.gif


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
zombi
сообщение Sep 22 2011, 08:31
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 2 076
Регистрация: 10-09-08
Пользователь №: 40 106



Цитата(ILYAUL @ Sep 22 2011, 09:23) *
срочно возникла необходимость сохранить 100 байт в области памяти

т.е. PUSH 100 байт

Цитата(demiurg_spb @ Sep 22 2011, 11:02) *
Главное при выходе из процедуры отмотать стек обратно! Таким макаром достигается реентерабельность функций

т.е. POP 100 байт или увеличение указателя на 100

Не вижу ничего необычного в том что процедура изменяющая указатель стека перед выходом должна его восстановить.
Что тут особенного? Или я что то не догоняю?
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Sep 22 2011, 08:48
Сообщение #14


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(zombi @ Sep 22 2011, 12:31) *
...Не вижу ничего необычного в том что процедура изменяющая указатель стека перед выходом должна его восстановить.Что тут особенного? Или я что то не догоняю?


Ваш апоннент говорит о чистке стэка вызывающей программой.
Вы подразумеваете очистку стэка вызываемой программой.

разные контракты на очистку стэка. и то и то имеет право на жизнь, но в одной программе лучше придерживаться одних правил (имхо конечно же).

(круглый)
ЗЫ
правда лихо соскочили с темы обработки прерываний sm.gif замечу что к прерываниям это вообще не относится.
ЗЫ
Чиссо по мне - не создавать таких проблем. Т.е. делать логику такой, чтоб данные перемещались минимально. т.е. рулят указатели и заранее резервированные места для данных.
Go to the top of the page
 
+Quote Post
Палыч
сообщение Sep 22 2011, 08:53
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(MKdemiurg @ Sep 22 2011, 11:12) *
Что будет если на вход внешнего прерывания( по срезу) прийдут два импульса с разницей в несколько мс( а может и меньше - прерывание от RTS - будильника ичасов) . Одно из прерываний пропадёт ?

Может пропасть. Первый импульс установит флаг. Если прерывание по какой-то причине не произайдет (например, по причине глобального запрета прерываний или при длительной работе процедуры обработки другого прерывания, которая выполняется в данный момент) до прихода второго импульса, то второго прерывания не будет. Грубо говоря: счетчик прерываний - однобитный (флаг прерывания) и больше чем до 1 считать не может.
Go to the top of the page
 
+Quote Post

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

 


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


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