|
Работа с прерываниями в WinAVR, Глобальные переменные в main и прерываниях |
|
|
|
Oct 17 2008, 11:12
|
Местный
  
Группа: Свой
Сообщений: 263
Регистрация: 2-02-07
Из: CN, Ukraine
Пользователь №: 24 970

|
Код #define PacketReceiveComplete INT5_vect
volatile uint64t_t DestMAC;
ISR(PacketReceiveComplete){ getDestMAC(&DestMAC); }
int main(void){ ... printf("%lx",DestMAC); } ps. мое личное IMHO, использование int такого размера на 8-мибитнике для хранения MAC адреса - не лучшая идея.
|
|
|
|
|
Oct 17 2008, 11:14
|

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

|
Цитата(studert @ Oct 17 2008, 14:07)  Что я делаю не так? Попробуйте так int main(void){ uint64t_t temp; ... cli(); temp= DestMAC; sei(); printf("%lx",temp); }
|
|
|
|
|
Oct 17 2008, 11:28
|
Частый гость
 
Группа: Свой
Сообщений: 76
Регистрация: 6-03-05
Из: Новосибирск
Пользователь №: 3 121

|
Цитата(Палыч @ Oct 17 2008, 18:14)  Попробуйте так
int main(void){ uint64t_t temp; ... cli(); temp= DestMAC; sei(); printf("%lx",temp); } Так тоже не работает, если при попытке отправить в порт DestMAC выводится мусор, то как присвоив мусор другой переменной от него избавиться? Где и как нужно объявлять глобальные переменные, чтобы они были доступны всем подпрограммам?
|
|
|
|
|
Oct 17 2008, 11:33
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(studert @ Oct 17 2008, 15:07)  Объявлена глобальная переменная, значение которой uint64t_t DestMAC; avr-libc-user-manual FAQ#1 Цитата(studert @ Oct 17 2008, 15:07)  printf("%lx",DestMAC); Уточните в avr-libc-user-manual поддерживает ли printf 64-битные типы. Цитата(studert @ Oct 17 2008, 15:07)  ISR(PacketReceiveComplete){ cli(); getDestMAC(&DestMAC); sei(); } Нельзя разрешать прерывания перед выходом из прерывания, они сами разрештся при выполнении инструкции RETI. Анатолий.
|
|
|
|
|
Oct 17 2008, 11:45
|
Частый гость
 
Группа: Свой
Сообщений: 76
Регистрация: 6-03-05
Из: Новосибирск
Пользователь №: 3 121

|
Цитата(SasaVitebsk @ Oct 17 2008, 18:27)  volatile забыли. Иначе оптимизатор может выкинуть чтение перед выдачей.
Непонятно зачем cli в прерывании. Хотя смотря как вы вектор объявляли. Ну cli это я от незнания поставил, первый раз с прерываниями работаю в этом компиляторе, до этого на асме только использовал. Я правильно понял, что компилятор сам поставит cli/sei? А volatile что-то тоже не помог. Может есть у кого пример, в котором по внешнему прерыванию изменяется какая-нибудь переменная, которая потом выводится в main?
Сообщение отредактировал studert - Oct 17 2008, 11:53
|
|
|
|
|
Oct 17 2008, 11:55
|
Частый гость
 
Группа: Свой
Сообщений: 76
Регистрация: 6-03-05
Из: Новосибирск
Пользователь №: 3 121

|
Цитата(aesok @ Oct 17 2008, 18:33)  avr-libc-user-manual FAQ#1 Уточните в avr-libc-user-manual поддерживает ли printf 64-битные типы. Нельзя разрешать прерывания перед выходом из прерывания, они сами разрештся при выполнении инструкции RETI.
Анатолий. Спасибо за ответ. Действительно принтф не поддерживает 64 бит.
|
|
|
|
|
Oct 17 2008, 12:04
|
Группа: Новичок
Сообщений: 11
Регистрация: 17-10-08
Пользователь №: 41 018

|
Цитата(aesok @ Oct 17 2008, 14:33)  Нельзя разрешать прерывания перед выходом из прерывания, они сами разрештся при выполнении инструкции RETI. Можно конечно. Не запрещено.
|
|
|
|
|
Oct 17 2008, 12:05
|
Участник

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

|
Цитата(studert @ Oct 17 2008, 15:07)  Задаю благозвучное название прерывания #define PacketReceiveComplete INT5_vect
Объявлена глобальная переменная, значение которой uint64t_t DestMAC;
Обработчик прерывания, функция getDestMAC записывает в переменную DestMAC нужные данные ISR(PacketReceiveComplete){ cli(); getDestMAC(&DestMAC); sei(); } int main(void){ ... printf("%lx",DestMAC); } Это не работает, печатает мусор,причем попытки изменить DestMAC main тоже неудачны, она не меняется. Что я делаю не так? 1) А просто printf у вас работает, если не использовать обработчиков прерываний по приему, по окончании передачи, по свободному регистру UDRn?
|
|
|
|
|
Oct 17 2008, 12:27
|
Частый гость
 
Группа: Свой
Сообщений: 76
Регистрация: 6-03-05
Из: Новосибирск
Пользователь №: 3 121

|
Цитата(mandrew @ Oct 17 2008, 19:05)  1) А просто printf у вас работает, если не использовать обработчиков прерываний по приему, по окончании передачи, по свободному регистру UDRn? Принтф работает, выводит все как положено, если 64 битные данные не кормить.
|
|
|
|
|
Oct 17 2008, 17:20
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(Kernigan @ Oct 17 2008, 16:04)  Цитата Нельзя разрешать прерывания перед выходом из прерывания, они сами разрештся при выполнении инструкции RETI Можно конечно. Не запрещено. 1. Лишняя инструкция SEI, прерывания все равно будут разрешенны при выполнении инструкции RETI. 2. При разрешении прерывани до возвращения из обработчика создаються условия что следующиу обработчик(и) вызовутся когда в стеке еще находиться адрес возврата и возможно локальные переменные текущего обработчика, что приводит к повышенному и неэффективному использованию опреративной памяти. 3. Специфично для GCC. Если функции нужно место в стеке, то нужно модифицировать регистр указателя стека. Пролог и эпилог обработчика прерывиня генерируеться из предположения что прерывания отключены и в них не выполняеться временное отключение прерываний при модификации указателя стека. Разрешая прерывания до эпилога возникают условия что обработчик прерывания может быть вызван когда указатель стека модифицирован только частично (старший байт уже изменен младший еще нет), что может привести к критическим последствиям. Анатолй.
|
|
|
|
|
Oct 17 2008, 18:51
|

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

|
Цитата(aesok @ Oct 17 2008, 21:20)  Пролог и эпилог обработчика прерывиня генерируеться из предположения что прерывания отключены и в них не выполняеться временное отключение прерываний при модификации указателя стека. На мой взляд такое предположение не совсем удачно. Компилятор ничего не должен предполагать - это прерогатива программиста. Иногда просто необходимо разрешать прерывания внутри обработчика прерывания. Выход видится такой: Код intX: прогол op1 op2 sei op3 .... op333 cli эпилог reti Может есть другие, более изящные варианты? Где в документации можно прочесть об этом нюансе?
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Oct 17 2008, 19:14
|
Знающий
   
Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484

|
Цитата(demiurg_spb @ Oct 17 2008, 22:51)  Иногда просто необходимо разрешать прерывания внутри обработчика прерывания. Выход видится такой: Код intX: прогол op1 op2 sei op3 .... op333 cli эпилог reti Это будет работать до того момента, пока кто нибудь не напишет: { sei() ... if(...) return; ... cli() } Цитата Где в документации можно прочесть об этом нюансе? http://gcc.gnu.org/onlinedocs/gcc-4.3.2/gc...tion-AttributesЦитата signal Use this attribute on the AVR to indicate that the specified function is a signal handler. The compiler will generate function entry and exit sequences suitable for use in a signal handler when this attribute is present. Interrupts will be disabled inside the function.
|
|
|
|
|
Oct 17 2008, 20:44
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(demiurg_spb @ Oct 17 2008, 21:51)  На мой взляд такое предположение не совсем удачно. Компилятор ничего не должен предполагать - это прерогатива программиста. Если компилятор ничего не будет предполагать, он будет связан по рукам при оптимизации. А прерогатива програмиста - управлять его предположениями. Предполагает же он, что переменная не меняется, пока он сам её не поменяет? Предполагает. Пока программиcт не отобъёт эту предполагалку при помощи слова volatile. С прерываниями - если нужно, чтобы данное прерывание всё выполнялось при разрешённых прерываниях, то Код ISR(INT0_vect,ISR_NOBLOCK) { } и прерывания будут разрешены первой командой обработчика, потом будут если надо для модификаций указателя стека запрещаться на пару команд. Цитата(demiurg_spb @ Oct 17 2008, 21:51)  Иногда просто необходимо разрешать прерывания внутри обработчика прерывания. Выход видится такой: ... Может есть другие, более изящные варианты? Где в документации можно прочесть об этом нюансе? Если нужно разрешить на части обработчика, то других вариантов и нет. Чтобы не було проблем, обозначеннх aesok, надо глянуть <util/atomic.h>Код #include <avr/io.h> #include <avr/interrupt.h> #include <util/atomic.h>
volatile uint8_t a, b;
ISR(INT0_vect) { ++a; NONATOMIC_BLOCK(NONATOMIC_FORCEOFF) { //+++ от сих PORTB |= 0x02; if( PINB & 0x01 ) return; // а тут запретятся перед уходом на эпилог PORTB |= 0x04; } //--- и до сих - прерывания разрешены ++b; } Это сделано на gcc-шном расширении C - атрибутах, приписывающих к переменным некие функции инициализации и очистки. По сути - конструкторы и деструкторы, выражаясь языком C++ Приведенный выше код эквивалентен С++ - ному Код #include <avr/io.h> #include <avr/interrupt.h> #include <util/atomic.h>
class noatomic_forceoff { public: noatomic_forceoff() { sei(); } ~noatomic_forceoff() { cli(); } };
volatile uint8_t a, b;
ISR(INT0_vect) { ++a; { noatomic_forceoff na; PORTB |= 0x02; if( PINB & 0x01 ) return; PORTB |= 0x04; } ++b; } вплоть до сгенерированного компиляторами кодаavr-gcc -std=c99 -O2 -S -mmcu=atmega88 avr-g++ -O2 -S -mmcu=atmega88 CODE __vector_1: /* prologue: frame size=0 */ push __zero_reg__ push __tmp_reg__ in __tmp_reg__,__SREG__ push __tmp_reg__ clr __zero_reg__ push r24 /* prologue end (size=6) */ lds r24,a subi r24,lo8(-(1)) sts a,r24 /* #APP */ sei /* #NOAPP */ sbi 37-0x20,1 sbic 35-0x20,0 rjmp .L2 sbi 37-0x20,2 /* #APP */ cli /* #NOAPP */ lds r24,b subi r24,lo8(-(1)) sts b,r24 rjmp .L5 .L2: /* #APP */ cli /* #NOAPP */ .L5: /* epilogue: frame size=0 */ pop r24 pop __tmp_reg__ out __SREG__,__tmp_reg__ pop __tmp_reg__ pop __zero_reg__ reti
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|