|
AVR ATmega32 прерывания |
|
|
|
Jun 14 2011, 11:28
|
Группа: Новичок
Сообщений: 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 и затем произойдет переброс в прерывание?
Заранее спасибо.
|
|
|
|
2 страниц
1 2 >
|
 |
Ответов
(1 - 26)
|
Jun 14 2011, 12:44
|
Участник

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

|
Всё зависит от того что в R0. Т.е. что было в SREG перед сохранением его в R0. Если флаг IE был сброшен, то ничего не произойдет, если утановлен - то запись млядшего байта успеет произойти - время реакции на прерывание 4 такта.
|
|
|
|
|
Jun 14 2011, 18:13
|

неотягощённый злом
     
Группа: Свой
Сообщений: 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 такт. Время реакции на прерывание - это то сколько тактов нужно процессору с момента запроса прерывания до начала выполнения обработчика прерывания. И всё это время процессор уже не выполняет фоновую программу как вы подумали, а помещает в стек адрес возврата и совершает переход на вектор прерывания. И только. Хотя мог бы и регистр статуса сохранить аппаратно, да и регистровые пары некоторые, а нет...
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Sep 21 2011, 13:20
|
Группа: Новичок
Сообщений: 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.
|
|
|
|
|
Sep 21 2011, 15:42
|

Профессионал
    
Группа: Свой
Сообщений: 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И вообще мне не понятно , что Вы делаете со стеком, зачем Вам менять его вершину в основной программе
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Sep 22 2011, 05:36
|

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

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

Профессионал
    
Группа: Свой
Сообщений: 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; Выталкиваем из стека
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Sep 22 2011, 06:23
|

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

|
QUOTE (demiurg_spb @ Sep 22 2011, 10:12)  Вы не поняли. Нет разницы Cи или асм. Нужен временный локальный буфер на 100 байт в процедуре. Ваши действия? Так . Сейчас я для себя пойму задачу: Я понял так - временный локальный буфер - срочно возникла необходимость сохранить 100 байт в области памяти , при этом заранее в .dseg он не был зарезервирован. И Вы предлагаете перенести вершину стека и просто затолкнуть туда данные? Правильно?
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Sep 22 2011, 08:02
|

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

|
Цитата(ILYAUL @ Sep 22 2011, 10:23)  Так . Сейчас я для себя пойму задачу: Я понял так - временный локальный буфер - срочно возникла необходимость сохранить 100 байт в области памяти , при этом заранее в .dseg он не был зарезервирован. И Вы предлагаете перенести вершину стека и просто затолкнуть туда данные? Правильно? Именно! Главное при выходе из процедуры отмотать стек обратно! Таким макаром достигается реентерабельность функций в противовес методу: Цитата заранее в .dseg ... зарезервирован Это конечно же не я придумал, а много-много лет назад мужики с бородами до пупа
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Sep 22 2011, 08:31
|

Гуру
     
Группа: Свой
Сообщений: 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 Не вижу ничего необычного в том что процедура изменяющая указатель стека перед выходом должна его восстановить. Что тут особенного? Или я что то не догоняю?
|
|
|
|
|
Sep 22 2011, 08:48
|
практикующий тех. волшебник
    
Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417

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

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

|
Цитата(zombi @ Sep 22 2011, 12:31)  Или я что то не догоняю? Не знаю чего вы не догоняете. Но чтобы не делать 100 раз push и потом 100 pop, ручками сдвигаем вершину стека (резервируя без инициализации на стеке N байт), что гораздо эффективнее со всех сторон. Потом используем этот участок памяти как нам заблагорассудится. Действительно просто.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Sep 22 2011, 09:34
|

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

|
QUOTE (demiurg_spb @ Sep 22 2011, 12:02)  Именно! Главное при выходе из процедуры отмотать стек обратно! Таким макаром достигается реентерабельность функций в противовес методу: Это конечно же не я придумал, а много-много лет назад мужики с бородами до пупа  Ничего не могу на это ответить , пока не попробую. Обычно я предполагаю или точно знаю сколько потребуется буфера. Но , конечно запомнил подход. Спасибо! MKdemiurgQUOTE Что будет если на вход внешнего прерывания( по срезу) прийдут два импульса с разницей в несколько мс( а может и меньше - прерывание от RTS - будильника ичасов) . Одно из прерываний пропадёт ? Просто непонятно .... каким образом такая ситуация может возникнуть? Часы и будильник - строго как-то привязаны к секундам , часы с мигами , да и ещё с установкой на них будильника , я пока не встречал. Считывайте с RTC статусный регистр и проверяйте флаги
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Sep 22 2011, 10:12
|
Знающий
   
Группа: Свой
Сообщений: 624
Регистрация: 15-06-10
Из: Россия
Пользователь №: 57 939

|
Цитата(ILYAUL @ Sep 22 2011, 12:34)  MKdemiurg каким образом такая ситуация может возникнуть? Часы и будильник - строго как-то привязаны к секундам , часы с мигами , да и ещё с установкой на них будильника , я пока не встречал. Считывайте с RTC статусный регистр и проверяйте флаги PCF8563 - можно запустить RTC и таймер. При совпадении будильника или конца счёта таймера - получаете прерывание. Можно активировать оба прерывания. Оба дадут спад в "0". Восстанавливается программно. Теоретически совпасть могут с точностью до миллисекунд. Если я в обработчике установку таймера сделаю... Я вот уже и подумал. Даже если прерывание "пропадёт" я просто в обработчике считаю флаги... Насколько я понял флаг прерывания обнуляется при входе в обработчик. Значит если придёт импульс во время обработки , то после выхода опять сработает прерывание... Как то так...
|
|
|
|
|
Sep 22 2011, 11:01
|

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

|
Цитата(zombi @ Sep 22 2011, 13:16)  Опять не понял. Где конкретно об этом говорится? Нигде. Он видимо попутал. Выделение и освобождение памяти на стеке-ли, на куче-ли происходит в нормальной ситуации ИМХО в одном контексте. Касаемо стека: в случае передачи/возвращения структур - снаружи (call-ret), в случае локального временного буфера - внутри (call-ret).
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Sep 22 2011, 11:07
|

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

|
Цитата(demiurg_spb @ Sep 22 2011, 12:12)  Не знаю чего вы не догоняете. Но чтобы не делать 100 раз push и потом 100 pop, ручками сдвигаем вершину стека (резервируя без инициализации на стеке N байт), что гораздо эффективнее со всех сторон. Потом используем этот участок памяти как нам заблагорассудится. Действительно просто. Т.е. гланая программа перед вызовом процедуры резервирует для неё Nбайт в области стека путём уменьшения указателя. После выполнения процедуры главная программа длжна восстановить указатель. Это ж обычный метод передачи параметров в функцию. Что здесь нового? И причем здесь прерывания?
|
|
|
|
|
Sep 22 2011, 11:21
|

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

|
Цитата(zombi @ Sep 22 2011, 15:07)  Т.е. гланая программа перед вызовом процедуры резервирует для неё Nбайт в области стека путём уменьшения указателя. После выполнения процедуры главная программа длжна восстановить указатель. Нет не так. Не об этом говорим, а о локальном стековом фрейме функции. Цитата Это ж обычный метод передачи параметров в функцию Это другое. Цитата Что здесь нового? А где про новизну-то вообще упоминается? Скорее наоборот я подчеркнул ранее что всё это придумали ещё во времена динозавров. Цитата И причем здесь прерывания? При том что на AVR8 нужно их блокировать на время модификации SPL+SPH. Какие ещё вопросы будут? Вы тему от начала меедленно перечитайте и не будет столько вопросов мимо кассы  Цитата(MKdemiurg @ Sep 22 2011, 11:12)  Чтоб не создавать новую тему спрошу тут( всё равно ТС уже давно пропал) Это зря вы так решили...
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Sep 22 2011, 11:23
|

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

|
QUOTE (MKdemiurg @ Sep 22 2011, 14:12)  PCF8563 - можно запустить RTC и таймер. При совпадении будильника или конца счёта таймера - получаете прерывание. Можно активировать оба прерывания. Оба дадут спад в "0". Восстанавливается программно. Теоретически совпасть могут с точностью до миллисекунд. Если я в обработчике установку таймера сделаю...
Я вот уже и подумал. Даже если прерывание "пропадёт" я просто в обработчике считаю флаги... Насколько я понял флаг прерывания обнуляется при входе в обработчик. Значит если придёт импульс во время обработки , то после выхода опять сработает прерывание... Как то так... Обнуляется флаг Вашего прерывания (MCU) а , данные которые Вы считаете с RTC - останутся до тех пор пока сами не обнулите. Да сработает , если Вы успеете сбросить предыдущее в самой микросхеме , на это у Вас есть секунда т.к если Вы установили , что пришло время прочитать часы , а флага будильника нет , то он может появится только спустя секунду. Вот Ваши биты : QUOTE Table 9 . Value descriptions for bits AF and TF Установлены оба - значит считаете часы и звените.
--------------------
Закон Мерфи:
Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
|
|
|
|
|
Sep 22 2011, 11:26
|

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

|
Цитата(ILYAUL @ Sep 22 2011, 13:34)  Ничего не могу на это ответить , пока не попробую. Обычно я предполагаю или точно знаю сколько потребуется буфера. Тут фишка не в том что вы знаете размер буфера наперёд, а в реентерабельности. Ваши процедуры нельзя вызывать из нескольких потоков одновременно и зачастую рекурсивно тоже... Цитата Но , конечно запомнил подход. Спасибо! Всегда пожалуйста!
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Sep 22 2011, 12:21
|

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

|
Цитата(demiurg_spb @ Sep 22 2011, 14:21)  Нет не так. Не об этом говорим, а о локальном стековом фрейме функции. Ну так я об этом и думал но мне пишут: Цитата(kolobok0 @ Sep 22 2011, 11:48)  Ваш апоннент говорит о чистке стэка вызывающей программой. Цитата(demiurg_spb @ Sep 22 2011, 14:26)  Тут фишка не в том что вы знаете размер буфера наперёд, а в реентерабельности. Ваши процедуры нельзя вызывать из нескольких потоков одновременно и зачастую рекурсивно тоже... А зачем может понадобиться реентерабельность обработчика прерываний?
|
|
|
|
|
Sep 23 2011, 04:48
|

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

|
Цитата(zombi @ Sep 22 2011, 16:21)  А зачем может понадобиться реентерабельность обработчика прерываний? Хороший вопрос! Я ждал его! (С) из х/ф "День радио" Обычно не зачем, но варианты возможны. Например одна и та же функция вызывается и в фоне и в обработчике, являясь по сути его телом.  PS: Я где-то говорил о реентерабельность обработчика прерываний?
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Sep 23 2011, 15:26
|

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

|
Цитата(demiurg_spb @ Sep 23 2011, 07:48)  Хороший вопрос! Я ждал его! (С) из х/ф "День радио" Цитата(demiurg_spb @ Sep 23 2011, 07:48)  Обычно не зачем, но варианты возможны. Например одна и та же функция вызывается и в фоне и в обработчике, являясь по сути его телом. Ага, теперь понятно. Т.о. вызываемая процедура "наглым образом" производит самозахват памяти в области стека, пользует её как хочет а перед выходом (вволю наигавшись) освобождает. Жаль что у меня нет задач чтоб это использовать. Цитата(demiurg_spb @ Sep 23 2011, 07:48)   PS: Я где-то говорил о реентерабельность обработчика прерываний? Нигде, мне просто было интересно Ваше мнение.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|