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

 
 
> Хочется программно инициировать прерывание, Но не INT0/INT1, как бы погламурнее
Rst7
сообщение May 20 2008, 11:52
Сообщение #1


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Тут задача возникла следующего характера. Как бы инициировать прерывание программным путем?

Самый простой способ - использовать INT0, например, и сконфигурировать прерывание по изменению состояния ноги (нога на вывод), в результате - достаточно шевельнуть ножкой (изменив ее, скажем OUT'ом в PINx) и флаг прерывания установится; соответственно, когда будет разрешено прерывание INT0 - оно и произойдет. Но, к сожалению, INT0 и INT1 заняты, надо изобретать что-то другое.

Вот мысль появилась использовать прерывание от компаратора, причем следующим образом:

Компаратор штатно выключен (он не нужен в проекте), для установки флага прерывания от него использовать последовательность
Код
ACSR=(1<<ACD)|(1<<ACIS1)|(1<<ACIS0); //Comparator Interrupt on Rising Output Edge.
ACSR=(1<<ACD)|(1<<ACIS1); //Comparator Interrupt on Falling Output Edge.


Т.е. переключить туда-сюда "по фронту/по спаду". На идею натолкнула фраза
Цитата
When changing the ACIS1/ACIS0 bits, the Analog Comparator Interrupt must be disabled by clearing its Interrupt Enable bit in the ACSR Register. Otherwise an interrupt can occur when the bits are changed.

в даташите.

К сожалению, сейчас негде попробовать этот чит. Посему пара вопросов:

1. Может кто делал такое и уже знает результат?
2. Может у кого есть под рукой макеточка, проверить бы?
3. А может кто гламурнее способ знает?


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
4 страниц V   1 2 3 > »   
Start new topic
Ответов (1 - 59)
prottoss
сообщение May 20 2008, 11:58
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Rst7 @ May 20 2008, 19:52) *
Тут задача возникла следующего характера. Как бы инициировать прерывание программным путем?
в scmRTOS, по моему, что то подобное реализовано именно для программных прерываний.


--------------------
Go to the top of the page
 
+Quote Post
VladimirYU
сообщение May 20 2008, 11:58
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 426
Регистрация: 5-04-07
Из: Санкт-Петербург
Пользователь №: 26 782



Цитата(Rst7 @ May 20 2008, 15:52) *
Тут задача возникла следующего характера. Как бы инициировать прерывание программным путем?

Самый простой способ - использовать INT0, например, и сконфигурировать прерывание по изменению состояния ноги (нога на вывод), в результате - достаточно шевельнуть ножкой (изменив ее, скажем OUT'ом в PINx) и флаг прерывания установится; соответственно, когда будет разрешено прерывание INT0 - оно и произойдет. Но, к сожалению, INT0 и INT1 заняты, надо изобретать что-то другое.

Вот мысль появилась использовать прерывание от компаратора, причем следующим образом:

Компаратор штатно выключен (он не нужен в проекте), для установки флага прерывания от него использовать последовательность
Код
ACSR=(1<<ACD)|(1<<ACIS1)|(1<<ACIS0); //Comparator Interrupt on Rising Output Edge.
ACSR=(1<<ACD)|(1<<ACIS1); //Comparator Interrupt on Falling Output Edge.


Т.е. переключить туда-сюда "по фронту/по спаду". На идею натолкнула фраза

в даташите.

К сожалению, сейчас негде попробовать этот чит. Посему пара вопросов:

1. Может кто делал такое и уже знает результат?
2. Может у кого есть под рукой макеточка, проверить бы?
3. А может кто гламурнее способ знает?


А почему хочется именно пограммное прерывание, почему нелзя обычный вызов обработчика.
Go to the top of the page
 
+Quote Post
prottoss
сообщение May 20 2008, 12:01
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Rst7 @ May 20 2008, 19:52) *
,Вот мысль появилась использовать прерывание от компаратора
Как раз от компаратора в scmRTOS и используют, но вроде как внешне что то к выводу компаратора припаивать надо... Лучше обратиться к первоисточнику. К сожалению адреса не знаю - но по моему в форуме про RTOS тема травой не заростает.


--------------------
Go to the top of the page
 
+Quote Post
Rst7
сообщение May 20 2008, 12:12
Сообщение #5


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
А почему хочется именно пограммное прерывание, почему нелзя обычный вызов обработчика.


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

Как бы так объяснить, нафиг это надо... Ну типа эмуляция прерываний с приоритетом...


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
sKWO
сообщение May 20 2008, 12:16
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Цитата(Rst7 @ May 20 2008, 14:52) *
Тут задача возникла следующего характера. Как бы инициировать прерывание программным путем?

Не знаю для чего Вам это нужно, но если строить програму на прерываниях то основной код я обычно пишу в следующем прерывании
Код
USART_UDRE_vect   /* USART, Data Register Empty */

а оно возникает когда пустой регистр данных передатчика УСАП


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
galjoen
сообщение May 20 2008, 12:25
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 841
Регистрация: 10-05-07
Из: Чебоксары (Россия)
Пользователь №: 27 640



Цитата(Rst7 @ May 20 2008, 15:52) *
Тут задача возникла следующего характера. Как бы инициировать прерывание программным путем?
3. А может кто гламурнее способ знает?

А использование прерывания от EEPROM не будет гламурным способом?
1. Думаю, что его никто не использует. По крайней мере я - ни разу.
2. Разрешается одной командой sbi EECR,EERIE.
3. Генерируется всё время пока EEWE сброшен (EEPROM не пишется).
Go to the top of the page
 
+Quote Post
Rst7
сообщение May 20 2008, 12:34
Сообщение #8


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
а оно возникает когда пустой регистр данных передатчика УСАП


Занято, и кроме того, как и следующий вариант

Цитата
А использование прерывания от EEPROM не будет гламурным способом?


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

Ну нечто такое:

Код
__interrupt void slow_irq(void)
{
  DISABLE_SLOW_IRQ();
  SLOW_IRQ_LOCK=1;
  __enable_interrupt();
  ....
  ....много всякой долгой каки...
  ....
  __disable_interrupt();
  SLOW_IRQ_LOCK=0;
  ENABLE_SLOW_IRQ();
}

__interrupt void fast_irq(void)
{
  DISABLE_SLOW_IRQ();
  __enable_interrupt();
  ....
  ....
  ....
  if (....) SET_SLOW_IRQ();
  ....
  ....
  __disable_interrupt();
  if (!SLOW_IRQ_LOCK) ENABLE_SLOW_IRQ();
}


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
Палыч
сообщение May 20 2008, 12:44
Сообщение #9


Гуру
******

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



Цитата(Rst7 @ May 20 2008, 14:52) *
Тут задача возникла следующего характера. Как бы инициировать прерывание программным путем?... Но, к сожалению, INT0 и INT1 заняты, надо изобретать что-то другое.
ИМХО, в начале нужно определиться - какие ресурсы у Вас свободны? В зависимости от используемого МК можно, наверное, использовать
INT0-INT7
EEPROM Ready
USART0 Data Register Empty
USART1 Data Register Empty
SPM Ready

Возможно, не обязательно дрыгать ногой для вызова INTx. Может быть "подрыгать" режимом - аналогично компаратору. Такая же мысль и мне приходила в голову, но не проверял...
Go to the top of the page
 
+Quote Post
Rst7
сообщение May 20 2008, 12:52
Сообщение #10


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
Как раз от компаратора в scmRTOS и используют


Ага, прерыванием от компаратора и пользуются. Щас посмотрел в сорсы. Только raise делается ногодрыгом. А у меня эти лапы заняты.

Цитата
INT0-INT7

Всего 2, оба заняты
Цитата
EEPROM Ready
USART0 Data Register Empty
USART1 Data Register Empty
SPM Ready

Все не годятся, причину объяснил выше.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
Палыч
сообщение May 20 2008, 13:01
Сообщение #11


Гуру
******

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



Не понятно, чем Вам не угодило прерывание от EEPROM. Если, память не используете, то "ручками" делаете чтение, и получаете прерывание. Не чуть не хуже дрыгания ногой для получения INTx.

Так какие ресурсы у Вас свободны? Как вариант - использование прерывания от свободного таймера. Настроить его на работу без прескалера с генерацией прерывания по одному тику. Разрешили прерывание - получили прерывание.
Go to the top of the page
 
+Quote Post
singlskv
сообщение May 20 2008, 13:01
Сообщение #12


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Rst7 @ May 20 2008, 16:52) *
Только raise делается ногодрыгом. А у меня эти лапы заняты.
А какие ноги свободные ? (если есть конечно)
и что из переферии не задействованно ?
и какой чип ?
Go to the top of the page
 
+Quote Post
andrvisht
сообщение May 20 2008, 13:01
Сообщение #13


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



Цитата(Rst7 @ May 20 2008, 15:52) *
Ага, прерыванием от компаратора и пользуются. Щас посмотрел в сорсы. Только raise делается ногодрыгом. А у меня эти лапы заняты.
Всего 2, оба заняты

Все не годятся, причину объяснил выше.

Код
ICR ?
Go to the top of the page
 
+Quote Post
Rst7
сообщение May 20 2008, 13:03
Сообщение #14


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
Если, память не используете,

Использую.

Кроме того, "The EEPROM Ready interrupt generates a constant interrupt
when EEPE is cleared."

Т.е. пока EEPE очищен, прерывание генерируется. А мне так не годится. Мне нужно флаг установить, а сбросится он при выполнении процедуры прерывания.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
Палыч
сообщение May 20 2008, 13:09
Сообщение #15


Гуру
******

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



Цитата(Rst7 @ May 20 2008, 16:03) *
Мне нужно флаг установить, а сбросится он при выполнении процедуры прерывания.
Руками сбросить в процедуре обработки прерывания - религия не позволяет?

Какой у Вас контроллер и какие ресурсы свободны?
Go to the top of the page
 
+Quote Post
Rst7
сообщение May 20 2008, 13:15
Сообщение #16


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
Разрешили прерывание - получили прерывание.


Да не годится мне так. Мне нужно раздельное управление flag и enable. Так понятнее?


Цитата
Руками сбросить в процедуре обработки прерывания - религия не позволяет?


Он не сбросится для EEPROM'а, единственный выход - запрещать, а мне так не годится...


Цитата
Какой у Вас контроллер и какие ресурсы свободны?


Разные контроллеры. На данный момент ATMega168.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
andrvisht
сообщение May 20 2008, 13:16
Сообщение #17


Местный
***

Группа: Свой
Сообщений: 298
Регистрация: 29-08-05
Пользователь №: 8 064



так и не понял, нога которая ICP используется ?
Go to the top of the page
 
+Quote Post
Rst7
сообщение May 20 2008, 13:24
Сообщение #18


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
ICP используется ?


Занята. Да и дрыгать ножками не хотелось бы, они могут пригодиться для других целей.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение May 20 2008, 13:31
Сообщение #19


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

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



Цитата(Rst7 @ May 20 2008, 15:52) *
Тут задача возникла следующего характера. Как бы инициировать прерывание программным путем?.............

Как-то не очень понятна вообще логика вопроса. Понятно , что программно это иногда необходимо ( кнопка - таймер) тут есть логика , но из Ваших пояснений не прослеживается мысль - зачем Вам это нужно.
У любого устройства в MK есть регистра флага - по которому и происходит прерывание ( устанавливается и сбрасывается программным путём в большинстве случаев) .
Но не понятно зачем Вам надо вызвать прерывание - зная, что оно точно произойдёт- затем, что-то сделать и при этом по сути прерывание не использовать . Не поняттно зачем при обработке (например входов порта) зачем-то дёрнуть прерывание компаратора или таймера или EEPROM и при этом узнать что pin1 порта установлен в 1


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

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
galjoen
сообщение May 20 2008, 13:39
Сообщение #20


Знающий
****

Группа: Свой
Сообщений: 841
Регистрация: 10-05-07
Из: Чебоксары (Россия)
Пользователь №: 27 640



Цитата(Rst7 @ May 20 2008, 16:34) *
Мне не нужно прерывание, запрос которого сам по себе устанавливается, мне нужно его запрос руками (программно) поднять только в нужный мне момент времени. Т.е. из более приоритетного прерывания запустить менее приоритетное после окончания обработки более приоритетного.

Так вроде с готовностью EEPROM всё хорошо получается. Только ещё флаг в ОЗУ нужно завести, а м.б. счётчик (от задачи зависит). В обработчике __interrupt void fast_irq(void) вместо if (....) SET_SLOW_IRQ(); пишите if (....) Счётчик++;, а в конце вместо if (!SLOW_IRQ_LOCK) ENABLE_SLOW_IRQ(); пишите if (!Счётчик) ENABLE_SLOW_IRQ();. А в обработчике __interrupt void slow_irq(void) в начале DISABLE_SLOW_IRQ() (==cbi EECR,EERIE), а в конце делаете Счётчик--; и ещё раз if (!Счётчик) ENABLE_SLOW_IRQ();

Ещё могу рекомендовать более экзотический способ: использования совпадений у таймеров/счётчиков. Там при обработке флаг прерывания сам сбрасывается.

2 Палыч
Чтобы прерывание от EEPROM возникло никакого чтения EEPROM делать не нужно. Оно сразу возникнет - после его разрешения (если в этот момент EEPROM не пишется/читается).
Go to the top of the page
 
+Quote Post
Rst7
сообщение May 20 2008, 13:49
Сообщение #21


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
Так вроде с готовностью EEPROM всё хорошо получается.


Тут следующий момент: счетчики надо инкрементировать/декрементировать с запрещенными прерываниями. Да еще и сохранять регистр SREG. К сожалению, это занимает слишком много времени, у меня тут жестко все...

Цитата
Как-то не очень понятна вообще логика вопроса.


Логика Вашего текста тоже не ясна ни разу wink.gif

Цитата
У любого устройства в MK есть регистра флага - по которому и происходит прерывание ( устанавливается и сбрасывается программным путём в большинстве случаев) .


Сбрасывается программным путем - да, устанавливается - нет. Из-за этого и весь сыр-бор.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
prottoss
сообщение May 20 2008, 13:53
Сообщение #22


Гуру
******

Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659



Цитата(Rst7 @ May 20 2008, 20:34) *
Мне не нужно прерывание, запрос которого сам по себе устанавливается, мне нужно его запрос руками (программно) поднять только в нужный мне момент времени. Т.е. из более приоритетного прерывания запустить менее приоритетное после окончания обработки более приоритетного.
Можно пойти таким путем - в конце более приоритетного прерывания закидывать в стек возврата адрес менее приоритетного прерывания. Правда, надо будет вставочку на асме соорудить, и после вставочки не должно буть, естественно, ни каких вызовов.


--------------------
Go to the top of the page
 
+Quote Post
Палыч
сообщение May 20 2008, 14:14
Сообщение #23


Гуру
******

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



Цитата(galjoen @ May 20 2008, 16:39) *
Чтобы прерывание от EEPROM возникло никакого чтения EEPROM делать не нужно. Оно сразу возникнет - после его разрешения (если в этот момент EEPROM не пишется/читается).
Да, конечно! Это результат спешки... Вместо "делаете чтение" - "разрешаете прерывание"...

Счетчик предлагаете завести для подсчета числа разрешений прерывания?

2 Rst7
Почему запрещать прерывания - не годиться? Это равнозначно сбросу флага. Желаете иметь два "рычага" управления: разрешение прерывания и флаг? Ну, и аппетиты у Вас... Так, что из ресурсов свободно?



Цитата(prottoss @ May 20 2008, 16:53) *
Можно пойти таким путем - в конце более приоритетного прерывания закидывать в стек возврата адрес менее приоритетного прерывания. Правда, надо будет вставочку на асме соорудить, и после вставочки не должно буть, естественно, ни каких вызовов.
Тагда уж и закидывание в стек адреса - не нужно: в конце процедуры обработки прерывания сделать вызов процедуры обработки другого прерывания. Но, автору вопроса понадобилось зачем-то настоящее прерывание

Цитата(Rst7 @ May 20 2008, 16:49) *
Тут следующий момент: счетчики надо инкрементировать/декрементировать с запрещенными прерываниями. Да еще и сохранять регистр SREG. К сожалению, это занимает слишком много времени, у меня тут жестко все...
Из-за этого - весь сыр-бор? Но, ведь запретить/разрешить прерывания - гораздо быстрее, чем вход/выход в/из прерывания...
Go to the top of the page
 
+Quote Post
galjoen
сообщение May 20 2008, 14:16
Сообщение #24


Знающий
****

Группа: Свой
Сообщений: 841
Регистрация: 10-05-07
Из: Чебоксары (Россия)
Пользователь №: 27 640



Цитата(Rst7 @ May 20 2008, 17:49) *
К сожалению, это занимает слишком много времени, у меня тут жестко все...

Кстати регистр можно сохранять в регистр адреса EEPROM EEARL (out 1 такт), или использовать его и EEARH как данные (в т.ч. командами cbi, sbi, sbic, sbis). Всегда так делаю у тех процессоров где они до 0x20.
А прерывание от 8ми битных таймеров/счётчиков по сравнению (если есть свободные) чем вас не устраивает?
Go to the top of the page
 
+Quote Post
=GM=
сообщение May 20 2008, 14:59
Сообщение #25


Ambidexter
*****

Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282



Цитата(Rst7 @ May 20 2008, 10:52) *
Тут задача возникла следующего характера. Как бы инициировать прерывание программным путем?
3. А может кто гламурнее способ знает?

А почему так нельзя: RCALL INTERRUPTVECTOR? Вот вам и будет вызов прерывания программным путём.


--------------------
Делай сразу хорошо, плохо само получится
Go to the top of the page
 
+Quote Post
defunct
сообщение May 20 2008, 15:03
Сообщение #26


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(Rst7 @ May 20 2008, 15:52) *
Все не годятся, причину объяснил выше.

Ну дык и устанавливайте руками - UDRIE = 1.
так же руками и убирайте - UDRIE = 0.

Вы вероятно не приняли во внимание, что прерывание можно сгенерить не только по условию события возбуждения прерывания, а и просто разрещением этого прерывания (с учетом, что все внешние факторы уже готовы сгененерить прерывание).. E.g. установить прерывание по уровню INT0, держать INT0 всегда в соотв уровне, а прерывание возбуждать не дерганием пина, а дерганием GIMSK.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение May 20 2008, 15:05
Сообщение #27


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Я использую от таймера. У меня мега640 - там этих таймеров.... smile.gif

Код
    if(Flag.EnShow)    TIMSK0=2;                            // Выполнить прерывание
Go to the top of the page
 
+Quote Post
defunct
сообщение May 20 2008, 15:11
Сообщение #28


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(Rst7 @ May 20 2008, 16:49) *
Сбрасывается программным путем - да, устанавливается - нет. Из-за этого и весь сыр-бор.

Зато маска чудесно контроллируется программным путем. Включать маску везде где нужно, тушить только в обработчике.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение May 20 2008, 15:11
Сообщение #29


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



2 GM - ты немного задачу не осознал. smile.gif

Например я делаю 100 прерываний от таймера, а вот после сотого мне надо выполнить хороший кусок работы. За это время придёт 4 прерывания от таймера. Короче надо в прерывании от таймера, по какому-то событию вызвать другое прерывание. Прямой вызов - не проходит, надо чтобы из того вернулась и вошла в новое.

smile.gif Короче не умею я объяснять. smile.gif Пусть кто другой попробует.
Go to the top of the page
 
+Quote Post
defunct
сообщение May 20 2008, 15:16
Сообщение #30


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(SasaVitebsk @ May 20 2008, 18:11) *
Например я делаю 100 прерываний от таймера, а вот после сотого мне надо выполнить хороший кусок работы. За это время придёт 4 прерывания от таймера.

Не, такой пример не пойдет, разобъют сразу тупым и в тоже время справедливым вопросом - почему бы не выполнить хороший кусок работы в основном цикле программы. smile.gif
Go to the top of the page
 
+Quote Post
Палыч
сообщение May 20 2008, 15:19
Сообщение #31


Гуру
******

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



Цитата(SasaVitebsk @ May 20 2008, 18:11) *
Прямой вызов - не проходит, надо чтобы из того вернулась и вошла в новое.
Почему - "не проходит"? Перед вызовом - разрешил прерывания - и все дела...
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение May 20 2008, 15:35
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Цитата(Палыч @ May 20 2008, 18:19) *
Почему - "не проходит"? Перед вызовом - разрешил прерывания - и все дела...

Надо выйти из предыдущего прерывания. Можно это конечно сделать и ручками, но зачем? Я, к примеру задействовал незадействованый таймер. Приведу пример ...

Код
#pragma    vector=TIMER1_COMPA_vect, INT7_vect                // Отображение картинки     Master, Slave
__interrupt    static void    Regeneration(void)
{
...
   NPrer_COMPA++;
   if(NPrer_COMPA==16)TIMSK0=2;                            // Выполнить прерывание
}
...
#pragma    vector=TIMER0_COMPA_vect                        // Исполнение комманд
__interrupt    static void    ShowActive(void)
{
....
TIMSK0=0;                // Запретить прерывание
__enable_interrupt();
....
}


Таким образом у меня второе прерывание выполняется 1 раз за 16 прерываний первого и может длиться несколько прерываний первого.
Go to the top of the page
 
+Quote Post
Палыч
сообщение May 20 2008, 15:41
Сообщение #33


Гуру
******

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



Цитата(SasaVitebsk @ May 20 2008, 18:35) *
Надо выйти из предыдущего прерывания.
Зачем? Экономия стека? Можно вызывать и не процедуру обработки прерывания, а обыкновенную процедуру... Из предыдущего прерывания выходить и входить в новое - вовсе не обязательно! От этого ничего не изменится
Go to the top of the page
 
+Quote Post
galjoen
сообщение May 20 2008, 15:51
Сообщение #34


Знающий
****

Группа: Свой
Сообщений: 841
Регистрация: 10-05-07
Из: Чебоксары (Россия)
Пользователь №: 27 640



Цитата(defunct @ May 20 2008, 19:16) *
Не, такой пример не пойдет, разобъют сразу тупым и в тоже время справедливым вопросом - почему бы не выполнить хороший кусок работы в основном цикле программы. smile.gif

Не. В основном цикле не пойдёт. Вдруг там уже что-то выполняется, тогда туда и вернёмся. Кроме того написано, что нужно быстро - каждый такт на счету. Т.е. видимо нужно сделать что-то более приоритетное чем основной цикл, но менее приоритетное, чем прерывания (некоторые). Например рассчёт CRC блока, который в флешку записать надо. В таких случаях приходится и с возможностью рекурсии бороться, и со стеком колдовать, и смотреть кого это мы прервали то. Только на асме такое делается (я делал). А тут видимо на C, используя прерывания, такое же хотят сделать.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение May 20 2008, 16:04
Сообщение #35


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Привет, телепаты smile.gif
1. Какая у Вас мега в проекте?

<удалил чушь>
Go to the top of the page
 
+Quote Post
Палыч
сообщение May 20 2008, 16:08
Сообщение #36


Гуру
******

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



Цитата(galjoen @ May 20 2008, 18:51) *
Т.е. видимо нужно сделать что-то более приоритетное чем основной цикл, но менее приоритетное, чем прерывания (некоторые).
О чём речь? Ну, нет в AVR приоритетов выполняемого кода! Или прерывания разрешены - прерывания возможны, или они запрещены - тогда прерывание никакое не произайдет! Reset - не всчёт! Нельзя в AVR выполнять код при разрешенных прирываниях, и, чтобы при этом одни прерывания могли прервать выполнение, а другие - нет (если они, конечно, все разрешены)! Приоритеты прерываний - это "из другой оперы"...
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение May 20 2008, 16:12
Сообщение #37


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



Вот уж не знаю как вам объяснить. smile.gif

Ещё раз! Обзовём процедуры прерывания по мере их написания в моём предыдущем посте - 1 и 2.

Представьте, что прерывание 1 выполняется каждую мс. Соответственно п2 исполняется каждые 16мс. Предположем, что длительность исполнения п1 составляет 100мкс, а длительность п2 составляет 10мс.

В вашем варианте, если не принять специальных мер прервётся исполнение процедуры1, после начала исполнения процедуры2. Мало этого во много раз возростёт контекст в п1, что совершенно неоправдано увеличит загрузку процессора, так как они часто вызываются. Неисключено, что может произойти крах, так как выход из п1 завершён не будет, а будет повторный вход. Ну и как минимум будет оверхед по стеку.

Итак недостатки я перечислил - какие преимущества?
Go to the top of the page
 
+Quote Post
Rst7
сообщение May 20 2008, 16:29
Сообщение #38


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Давайте я попробую все-таки подробностей добавить.

Есть 4 задачи. В порядке возрастания приоритетов:

1. Основной поток (тот который main()). На данный момент там банальный for(;;). Чего там будет, я пока не знаю, и поэтому, этот поток трогать мне нельзя.
2. Задача обработки. Длительная, выполняется намного дольше, чем промежуток между вызовами задач 3,4. Во время выполнения должны уметь получать управление задачи 3,4, причем с минимальным временем отклика (особенно 4). Запуск задачи происходит от события. По окончанию обработки задача засыпает до следующего события.
3. Задача - не самое приоритетное прерывание. От таймера, но вызывается часто - 256/512 тактов. В задаче - по быстренькому опрос периферии и по результатам - возможна генерация события для задачи 2. Во время выполнения этой задачи необходимо обеспечить возможность быстрого реагирования на прерывание для задачи 4.
4. Самое приоритетное прерывание. Входит, выполняет дело, по результатам дела генерирует или не генерирует событие, выходит.

Да, забыл. Задача 1 тоже потом может будет генерить события для задачи 2, а может и не будет.

Для такого менеджмента задач идеально использовать RTOS, но есть одно но - пока переключаются контексты поезд задачи 4 уходит далеко - в смысле, время реакции не устраивает. Значит, надо делать подобие RTOS, но с минимальными временами нахождения в состояниях c запретом прерываний.

План у меня таков - задача 2 - это обработчик прерывания, запрос на выполнение которого я могу создать в любой момент (это генерация события), а вот обработать - только тогда, когда не выполняются задачи 3 или 4 (и не находимся внутри задачи 2, дабы не допустить вложенности). Для этого мне и необходимо раздельное управление флагом запроса и битом разрешения прерывания.

Вариант со счетчиком плохо проходит в связи с тем, что увеличение/уменьшение счетчика требует сохранения SREG (с последующим восстановлением) и работу с самим счетчиком до разрешения прерываний.


Вот примерно такой код
Код
#define TASK2_LOCK GPIOR0_Bit0
#define TASK3_LOCK GPIOR0_Bit1

#define DISABLE_TASK2() {asm("PUSH R16");ACSR=(1<<ACD)|(1<<ACIS1);asm("POP R16");}
#define ENABLE_TASK2() {asm("PUSH R16");ACSR=(1<<ACD)|(1<<ACIS1)|(1<<ACIE);asm("POP R16");}
#define WAKEUP_TASK2() {ACSR=(1<<ACD)|(1<<ACIS1)|(1<<ACIS0);}

#pragma diag_suppress=Ta006
__interrupt void TASK2(void)
{
  __no_operation();
  //....
  //....много всякой долгой каки...
  main(); //Например так
  //....
  __no_operation();
}
#pragma diag_default=Ta006


#pragma vector=ANA_COMP_vect
__interrupt __raw void TASK2dispatch(void)
{
  DISABLE_TASK2();
  TASK2_LOCK=1;
  __enable_interrupt();
  ((void(*)(void))TASK2)();  
  __disable_interrupt();
  TASK2_LOCK=0;
  ENABLE_TASK2();
}

#pragma diag_suppress=Ta006
__interrupt void TASK3(void)
{
  __no_operation();
  //....
  //....не очень много всякой долгой каки...
  if (PINB_Bit0) WAKEUP_TASK2(); //К примеру
  //....
  __no_operation();
}
#pragma diag_default=Ta006

#pragma vector=TIMER0_OVF_vect
__interrupt __raw void TASK3dispatch(void)
{
  if (TASK3_LOCK) return;
  TASK3_LOCK=1;
  DISABLE_TASK2();
  __enable_interrupt();
  ((void(*)(void))TASK3)();  
  __disable_interrupt();
  TASK3_LOCK=0;
  if (!TASK2_LOCK) ENABLE_TASK2();
}

#pragma vector=INT0_vect
__interrupt void TASK4(void)
{
  //Тут тоже колдовство, запрещаем все прерывания, например
  TIMSK0=0;
  //Запрещаем и TASK2
  DISABLE_TASK2();
  __enable_interrupt();
  //Чего-то делаем, тут еще бывает INT1, но это уже не суть
  __disable_interrupt();
  if (PINB_Bit1) WAKEUP_TASK2(); //К примеру
  TIMSK0=1<<TOV0;
  if (!TASK2_LOCK) ENABLE_TASK2();
}


А вот чего выходит после компилятора
Код
        RSEG CODE:CODE:NOROOT(1)
//  176 __interrupt void TASK2(void)
TASK2:
//  177 {
        ST      -Y, R24
        ST      -Y, R31
        ST      -Y, R30
        ST      -Y, R3
        ST      -Y, R2
        ST      -Y, R1
        ST      -Y, R0
        ST      -Y, R23
        ST      -Y, R22
        ST      -Y, R21
        ST      -Y, R20
        ST      -Y, R19
        ST      -Y, R18
        ST      -Y, R17
        ST      -Y, R16
        IN      R24, 0x3F
//  178   __no_operation();
        NOP
//  179   //....
//  180   //....много всякой долгой каки...
//  181   main(); //Например так
        RCALL   main
//  182   //....
//  183   __no_operation();
        NOP
//  184 }
        OUT     0x3F, R24
        LD      R16, Y+
        LD      R17, Y+
        LD      R18, Y+
        LD      R19, Y+
        LD      R20, Y+
        LD      R21, Y+
        LD      R22, Y+
        LD      R23, Y+
        LD      R0, Y+
        LD      R1, Y+
        LD      R2, Y+
        LD      R3, Y+
        LD      R30, Y+
        LD      R31, Y+
        LD      R24, Y+
        RETI
//  185 #pragma diag_default=Ta006
//  186
//  187
//  188 #pragma vector=ANA_COMP_vect

        RSEG CODE:CODE:NOROOT(1)
//  189 __interrupt __raw void TASK2dispatch(void)
TASK2dispatch:
//  190 {
//  191   DISABLE_TASK2();
        PUSH R16
        LDI     R16, 130
        OUT     0x30, R16
        POP R16
//  192   TASK2_LOCK=1;
        SBI     0x1E, 0x00
//  193   __enable_interrupt();
        SEI
//  194   ((void(*)(void))TASK2)();  
        RCALL   TASK2
//  195   __disable_interrupt();
        CLI
//  196   TASK2_LOCK=0;
        CBI     0x1E, 0x00
//  197   ENABLE_TASK2();
        PUSH R16
        LDI     R16, 138
        OUT     0x30, R16
        POP R16
//  198 }
        RETI
        REQUIRE _A_ACSR
        REQUIRE _A_GPIOR0
//  199
//  200 #pragma diag_suppress=Ta006

        RSEG CODE:CODE:NOROOT(1)
//  201 __interrupt void TASK3(void)
TASK3:
//  202 {
        ST      -Y, R16
//  203   __no_operation();
        NOP
//  204   //....
//  205   //....не очень много всякой долгой каки...
//  206   if (PINB_Bit0) WAKEUP_TASK2(); //К примеру
        SBIS    0x03, 0x00
        RJMP    ??TASK3_0
        LDI     R16, 131
        OUT     0x30, R16
//  207   //....
//  208   __no_operation();
??TASK3_0:
        NOP
//  209 }
        LD      R16, Y+
        RETI
        REQUIRE _A_ACSR
        REQUIRE _A_PINB
//  210 #pragma diag_default=Ta006
//  211
//  212 #pragma vector=TIMER0_OVF_vect

        RSEG CODE:CODE:NOROOT(1)
//  213 __interrupt __raw void TASK3dispatch(void)
TASK3dispatch:
//  214 {
//  215   if (TASK3_LOCK) return;
        SBIC    0x1E, 0x01
        RJMP    ??TASK3dispatch_0
//  216   TASK3_LOCK=1;
        SBI     0x1E, 0x01
//  217   DISABLE_TASK2();
        PUSH R16
        LDI     R16, 130
        OUT     0x30, R16
        POP R16
//  218   __enable_interrupt();
        SEI
//  219   ((void(*)(void))TASK3)();  
        RCALL   TASK3
//  220   __disable_interrupt();
        CLI
//  221   TASK3_LOCK=0;
        CBI     0x1E, 0x01
//  221   if (!TASK2_LOCK) ENABLE_TASK2();
        SBIC    0x1E, 0x00
        RJMP    ??TASK3dispatch_0
        PUSH R16
        LDI     R16, 138
        OUT     0x30, R16
        POP R16
??TASK3dispatch_0:
        RETI
        REQUIRE _A_ACSR
        REQUIRE _A_GPIOR0
//  222 }
//  223
//  224 #pragma vector=INT0_vect

        RSEG CODE:CODE:NOROOT(1)
//  225 __interrupt void TASK4(void)
TASK4:
//  226 {
        ST      -Y, R17
        ST      -Y, R16
        IN      R17, 0x3F
//  227   //Тут тоже колдовство, запрещаем все прерывания, например
//  228   TIMSK0=0;
        LDI     R16, 0
        STS     110, R16
//  229   //Запрещаем и TASK2
//  230   DISABLE_TASK2();
        PUSH R16
        LDI     R16, 130
        OUT     0x30, R16
        POP R16
//  231   __enable_interrupt();
        SEI
//  232   //Чего-то делаем, тут еще бывает INT1, но это уже не суть
//  233   __disable_interrupt();
        CLI
//  234   if (PINB_Bit1) WAKEUP_TASK2(); //К примеру
        SBIS    0x03, 0x01
        RJMP    ??TASK4_0
        LDI     R16, 131
        OUT     0x30, R16
//  235   TIMSK0=1<<TOV0;
??TASK4_0:
        LDI     R16, 1
        STS     110, R16
//  236   if (!TASK2_LOCK) ENABLE_TASK2();
        SBIC    0x1E, 0x00
        RJMP    ??TASK4_1
        PUSH R16
        LDI     R16, 138
        OUT     0x30, R16
        POP R16
//  237 }
??TASK4_1:
        OUT     0x3F, R17
        LD      R16, Y+
        LD      R17, Y+
        RETI


Вариант с прерываниями хорош еще и тем, что в задаче 1 я могу выполнить WAKEUP_TASK2();ENABLE_TASK2() - и сразу полетит выполять задачу 2. Все приоритеты красиво соблюдаются.


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
Палыч
сообщение May 20 2008, 16:34
Сообщение #39


Гуру
******

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



Цитата(SasaVitebsk @ May 20 2008, 19:12) *
В вашем варианте, если не принять специальных мер прервётся исполнение процедуры1, после начала исполнения процедуры2. Мало этого во много раз возростёт контекст в п1, что совершенно неоправдано увеличит загрузку процессора, так как они часто вызываются. Неисключено, что может произойти крах, так как выход из п1 завершён не будет, а будет повторный вход. Ну и как минимум будет оверхед по стеку.
Как сделать так, чтобы контекст не возрастал - уже обсуждалось... Крах при повторном входе? С чего бы это?
Обсуждение, кажется, ушло в сторону от заданного вопроса... Как я понял автора (пост №21): ему нужно изменить счетчики до возврата в основную программу, но чтобы при этом была возможность прерывания выполнять. Самое простое решение - прерывания разрешить.
Go to the top of the page
 
+Quote Post
galjoen
сообщение May 20 2008, 16:52
Сообщение #40


Знающий
****

Группа: Свой
Сообщений: 841
Регистрация: 10-05-07
Из: Чебоксары (Россия)
Пользователь №: 27 640



Цитата(Палыч @ May 20 2008, 20:08) *
Приоритеты прерываний - это "из другой оперы"...

Именно такую задачу я имел ввиду и решал (с приоритетами прерываний). Для этого обработчики располагаются во FLASH определённым образом. Чем выше приоритет, тем в более младших адресах обработчик. Основной цикл (низший приоритет) в самых старших адресах. При входе в обработчик - прерывания с младшими приоритетами запрещаются. В обработчике прерывания - прерывания разрешены. По адресу возврата (реально нужен только старший байт) в стеке перед выходом определяется какие прерывания разрешить (дополнительно к уже разрешённым). Т.е. получается система прерываний (и выполняемого кода) с приоритетами. И без RTOS. Из-за этого быстро между задачами переключается.

В простых случаях (мало приоритетов) можно флагами обойтись. А для флагов какой-нибудь неиспользуемый регистр ввода-вывода (адрес до 0x20) использовать - для скорости. Я обычно там где такого специального нет (в AT90 есть) регистры адреса EEPROM использую.
Go to the top of the page
 
+Quote Post
singlskv
сообщение May 20 2008, 18:19
Сообщение #41


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Не знаю точно поможет ли это Вам в конкретной задачке, но я бы размышлял примерно так:
>>4. Самое приоритетное прерывание. Входит, выполняет дело, по результатам дела генерирует или >>не генерирует событие, выходит.
Ну вот это явно претендент на свое собственное прерывание.

>>3. Задача - не самое приоритетное прерывание. От таймера, но вызывается часто - 256/512 тактов. В >>задаче - по быстренькому опрос периферии и по результатам - возможна генерация события для >>задачи 2. Во время выполнения этой задачи необходимо обеспечить возможность быстрого >>реагирования на прерывание для задачи 4.
типичное таймерное прерывание, для разрешения других прерываний достаточно "легко"
делается сохранение контекста(если конечно задачка действительно простенькая...)

задачки 1 и 2 разумнее(скорее всего, делать в основном цикле), для
задачки N2 возможно подойдет просто опрос полингом флага другого таймера(специально закрепленного за этой задачкой)
Go to the top of the page
 
+Quote Post
ReAl
сообщение May 20 2008, 20:31
Сообщение #42


Нечётный пользователь.
******

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



Цитата(prottoss @ May 20 2008, 15:01) *
Как раз от компаратора в scmRTOS и используют, но вроде как внешне что то к выводу компаратора припаивать надо... Лучше обратиться к первоисточнику. К сожалению адреса не знаю - но по моему в форуме про RTOS тема травой не заростает.
Ничего припаивать не надо.
Но одна нога занята.
Один из входов компаратора ставится на внутренний ИОН, второй остаётся на ножке, ножка ставится на выход. Этого достаточно.

В порт avr-gcc в примеры внесён ещё и другой вариант - используется прерывание SPM_ready (считается, что не используется при работе приложения, а не загрузчика).
При необходимости вызвать прерывание поднимается бит SPMIE, в обработчике он сбрасывается.
Ничего плохого в таком варианте не вижу.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
singlskv
сообщение May 20 2008, 20:50
Сообщение #43


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Если свободен пин nSS(SPI SlaveSelect) я бы еще подумал насчет него...
ну типа:
Thus, when interrupt-driven SPI transmission is used in Master mode, and there exists a possibility
that SS is driven low, the interrupt should always check that the MSTR bit is still set. If the
MSTR bit has been cleared by a slave select, it must be set by the user to re-enable SPI Master
mode.
Go to the top of the page
 
+Quote Post
defunct
сообщение May 20 2008, 20:56
Сообщение #44


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(galjoen @ May 20 2008, 18:51) *
Не. В основном цикле не пойдёт. Вдруг там уже что-то выполняется, тогда туда и вернёмся. Кроме того написано, что нужно быстро - каждый такт на счету.

Смотря как построен основной цикл.
У меня в основном цикле выполняется диспетчер задач, точнее даже диспетчер функций-обработчиков событий. Т.к. задачи выполняются бесконечно, а функции - конечно и быстро. Функции делятся по приоритетам. Приоритет драйверов периферии (диспетчер крутит их постоянно) и пользовательские приоритеты. Работает все это как часы. Никаких проблем с сохранением контекстов, никаких накладных расходов на отдельные стеки задач.
В прерываниях устаналивается готовность соотв. функций. В основном цикле - производится запуск обработчика события.
Насчет каждый такт на счету - не верю, не может каждый такт быть на счету для чего-то настолько длительного, что ест аж 4 периода таймера и в то же время настолько редкого, что происходит раз в 100 периодов таймера. Нестукуется с таким событием понятие каждый такт на счету.
Go to the top of the page
 
+Quote Post
ReAl
сообщение May 20 2008, 21:03
Сообщение #45


Нечётный пользователь.
******

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



Кстати, я очень обижен на атмел в том, что битики force output compare у таймеров не вызывают соответствующее прерывание output compare :-(


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
singlskv
сообщение May 20 2008, 21:16
Сообщение #46


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(defunct @ May 21 2008, 00:56) *
Насчет каждый такт на счету - не верю, не может каждый такт быть на счету для чего-то настолько длительного, что ест аж 4 периода таймера и в то же время настолько редкого, что происходит раз в 100 периодов таймера. Нестукуется с таким событием понятие каждый такт на счету.
Ну и почему же это не стыкуется ?
допустим хочу:
- передачу по SPI на максимальной скорости(кб этак 250-500 в сек) но при этом чтобы
джиттер был минимален и предсказуем
- опрос кнопок(типа процесс в 100 раз более медленный)
- запись в EEPROM когда надо(тоже не быстро).
- итд итп

ну и кто мешает это все совместить ?


Цитата(ReAl @ May 21 2008, 01:03) *
Кстати, я очень обижен на атмел в том, что битики force output compare у таймеров не вызывают соответствующее прерывание output compare :-(
А Вы ими пробовали вобще пользоваться ? (битиками)
я нет, поэтому и интересно...
но кстати таймером тож можно чего-нить такое намутить, тока топикстартер не сознается какие
узлы кроме комаратора у него еще не задействованны...
Go to the top of the page
 
+Quote Post
defunct
сообщение May 20 2008, 21:19
Сообщение #47


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(singlskv @ May 21 2008, 00:11) *
Ну и почему же это не стыкуется ?

Несктыкуется это событие (длиной в 4 периода таймера) с надобностью обработки в прерывании.

Цитата
допустим хочу:
- передачу по SPI на максимальной скорости(кб этак 250-500 в сек) но при этом чтобы
джиттер был минимален и предсказуем
- опрос кнопок(типа процесс в 100 раз более медленный)
- запись в EEPROM когда надо(тоже не быстро).
- итд итп

ну и кто мешает это все совместить ?

Ничто и не помешает все это совместить если обработку события длиной в 4 периода таймера кинуть в основной цикл.
Go to the top of the page
 
+Quote Post
singlskv
сообщение May 20 2008, 21:35
Сообщение #48


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(defunct @ May 21 2008, 01:19) *
Несктыкуется это событие (длиной в 4 периода таймера) с надобностью обработки в прерывании.
Ничто и не помешает все это совместить если обработку события длиной в 4 периода таймера кинуть в основной цикл.
А кто сказал что это событие обязательно нужно обработать за один присест ?
Вне зависимости от того где оно будет обрабатывться, всегда есть возможность
обработать его по частям.
Те просто делаем автомат обработки события с внутренним разбиением на части...

Те например пусть нам нужно записать X байт в EEPROM,
запись каждого байта это процесс который может растянуться на очень много периодов
нашего таймера, но у нас автомат который запустил запись X байтов и пока они все не записались
он не освободился.
Ну конечно если там голые рассчеты без всяких ожиданий то они конечно должны
жить в главном цикле...
Go to the top of the page
 
+Quote Post
galjoen
сообщение May 20 2008, 21:59
Сообщение #49


Знающий
****

Группа: Свой
Сообщений: 841
Регистрация: 10-05-07
Из: Чебоксары (Россия)
Пользователь №: 27 640



Цитата(defunct @ May 21 2008, 01:19) *
Несктыкуется это событие (длиной в 4 периода таймера) с надобностью обработки в прерывании.

Тут прерывание ТОЛЬКО для того, чтоб приоритет этого события поднять, а основной цикл отдать кому то другому (на, делай в нём что хочешь, всё равно мне не навредишь).
Go to the top of the page
 
+Quote Post
defunct
сообщение May 20 2008, 23:30
Сообщение #50


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(singlskv @ May 21 2008, 00:35) *
Те просто делаем автомат обработки события с внутренним разбиением на части...

Ну так ведь ничто не мешает этот автомат сделать в основном цикле. Ввести там сколько надо приоритетов 10-100-1000 (на скоко памяти хватит) и следовать им.

Цитата
Тут прерывание ТОЛЬКО для того, чтоб приоритет этого события поднять

Если только для этого, то обрабатывать можно в том же прерывании, зачем еще одно плодить?
результат одинаковый будет.
Go to the top of the page
 
+Quote Post
Дон Амброзио
сообщение May 21 2008, 05:13
Сообщение #51


Местный
***

Группа: Участник*
Сообщений: 323
Регистрация: 11-02-08
Пользователь №: 34 947



У меня для "быстрых" потоков, которые должны вызваться не позднее одного тика таймера после возникновения Event-а, требующего их вмешательства, есть регистр , в котором каждый битик является Ready-флагом соответствующего потока. И перед выходом из ISR системного таймера я проверяю не стоит ли Ready-флажок какого-нить потока. Если стоит, то запускаю соответ.поток в порядке приоритета (от 7 к 0 )


--------------------
После устранения бага в программе она стала работать....хуже
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение May 21 2008, 05:44
Сообщение #52


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(defunct @ May 21 2008, 02:30) *
Ну так ведь ничто не мешает этот автомат сделать в основном цикле. Ввести там сколько надо приоритетов 10-100-1000 (на скоко памяти хватит) и следовать им.

Автоматами только в основном цикле, как правило, не обойтись. У меня обычно автоматы и на процессах в прерываниях.

Признаюсь, что тоже отношусь к темным, которые не понимают, зачем это все нужно. Приоритеты двух прерываний реализуются (извращенно smile.gif )несимметричностью разрешения прерывания (в одном ISR разрешаем, в другом нет), защита от переполнения стека в случае длинного и/или чрезмерно частого более приоритетного прерывания реализуется счетчиком низкоприоритетного прерывания.

__interrupt void low_priority_interrupt()
{ interrupt_no++;
if (interrupt_no>1) DISABLE_HIGH_PRIORITY_INTERRUPT();
__enable_interrupt();
...
}
Ну и попытка все устройства сделать на AVR , выжимая все соки? Даже в 8080 была система приоритетных прерываний, что других контроллеров не существует?


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Rst7
сообщение May 21 2008, 05:48
Сообщение #53


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Ну вообщем, проверил на железе - не приводит к установке флага прерывания от компаратора дрыг режимом фронт/спад. Плохо, конечно. Пришлось перенести на прерывание от EEPROM и завести флаг запроса. Теперь это выглядит примерно так
Код
#define TASK2_LOCK GPIOR0_Bit0
#define TASK3_LOCK GPIOR0_Bit1
#define TASK2_WAKEUP GPIOR0_Bit2

#define DISABLE_TASK2() {EECR_EERIE=0;}
#define ENABLE_TASK2() {EECR_EERIE=1;}
#define WAKEUP_TASK2() {TASK2_WAKEUP=1;}

#pragma diag_suppress=Ta006
__interrupt void TASK2(void)
{
  __no_operation();
  //....
  //....много всякой долгой каки...
  main(); //Например так
  //....
  __no_operation();
}
#pragma diag_default=Ta006


#pragma vector=EE_RDY_vect
__interrupt __raw void TASK2dispatch(void)
{
  DISABLE_TASK2();
  TASK2_LOCK=1;
  TASK2_WAKEUP=0;
  __enable_interrupt();
  ((void(*)(void))TASK2)();  
  __disable_interrupt();
  TASK2_LOCK=0;
  if (TASK2_WAKEUP) ENABLE_TASK2();
}

#pragma diag_suppress=Ta006
__interrupt void TASK3(void)
{
  __no_operation();
  //....
  //....не очень много всякой долгой каки...
  if (PINB_Bit0) WAKEUP_TASK2(); //К примеру
  //....
  __no_operation();
}
#pragma diag_default=Ta006

#pragma vector=TIMER0_OVF_vect
__interrupt __raw void TASK3dispatch(void)
{
  if (TASK3_LOCK) return;
  TASK3_LOCK=1;
  DISABLE_TASK2();
  __enable_interrupt();
  ((void(*)(void))TASK3)();  
  __disable_interrupt();
  TASK3_LOCK=0;
  if (TASK2_LOCK) return;
  if (TASK2_WAKEUP) ENABLE_TASK2();
}

#pragma vector=INT0_vect
__interrupt void TASK4(void)
{
  //Тут тоже колдовство, запрещаем все прерывания, например
  TIMSK0=0;
  //Запрещаем и TASK2
  DISABLE_TASK2();
  __enable_interrupt();
  //Чего-то делаем, тут еще бывает INT1, но это уже не суть
  __disable_interrupt();
  if (PINB_Bit1) WAKEUP_TASK2(); //К примеру
  TIMSK0=1<<TOV0;
  if (TASK3_LOCK) return;
  if (TASK2_LOCK) return;
  if (TASK2_WAKEUP) ENABLE_TASK2();
}


И код
Код
        RSEG CODE:CODE:NOROOT(1)
//   48 __interrupt void TASK2(void)
TASK2:
//   49 {
        ST      -Y, R24
        ST      -Y, R31
        ST      -Y, R30
        ST      -Y, R3
        ST      -Y, R2
        ST      -Y, R1
        ST      -Y, R0
        ST      -Y, R23
        ST      -Y, R22
        ST      -Y, R21
        ST      -Y, R20
        ST      -Y, R19
        ST      -Y, R18
        ST      -Y, R17
        ST      -Y, R16
        IN      R24, 0x3F
//   50   __no_operation();
        NOP
//   51   //....
//   52   //....много всякой долгой каки...
//   53   main(); //Например так
        RCALL   main
//   54   //....
//   55   __no_operation();
        NOP
//   56 }
        OUT     0x3F, R24
        LD      R16, Y+
        LD      R17, Y+
        LD      R18, Y+
        LD      R19, Y+
        LD      R20, Y+
        LD      R21, Y+
        LD      R22, Y+
        LD      R23, Y+
        LD      R0, Y+
        LD      R1, Y+
        LD      R2, Y+
        LD      R3, Y+
        LD      R30, Y+
        LD      R31, Y+
        LD      R24, Y+
        RETI
//   57 #pragma diag_default=Ta006
//   58
//   59
//   60 #pragma vector=EE_RDY_vect

        RSEG CODE:CODE:NOROOT(1)
//   61 __interrupt __raw void TASK2dispatch(void)
TASK2dispatch:
//   62 {
//   63   DISABLE_TASK2();
        CBI     0x1F, 0x03
//   64   TASK2_LOCK=1;
        SBI     0x1E, 0x00
//   65   TASK2_WAKEUP=0;
        CBI     0x1E, 0x02
//   66   __enable_interrupt();
        SEI
//   67   ((void(*)(void))TASK2)();  
        RCALL   TASK2
//   68   __disable_interrupt();
        CLI
//   69   TASK2_LOCK=0;
        CBI     0x1E, 0x00
//   70   if (TASK2_WAKEUP) ENABLE_TASK2();
        SBIC    0x1E, 0x02
        SBI     0x1F, 0x03
//   71 }
??TASK2dispatch_0:
        RETI
        REQUIRE _A_EECR
        REQUIRE _A_GPIOR0
//   72
//   73 #pragma diag_suppress=Ta006

        RSEG CODE:CODE:NOROOT(1)
//   74 __interrupt void TASK3(void)
TASK3:
//   75 {
//   76   __no_operation();
        NOP
//   77   //....
//   78   //....не очень много всякой долгой каки...
//   79   if (PINB_Bit0) WAKEUP_TASK2(); //К примеру
        SBIC    0x03, 0x00
        SBI     0x1E, 0x02
//   80   //....
//   81   __no_operation();
??TASK3_0:
        NOP
//   82 }
        RETI
        REQUIRE _A_GPIOR0
        REQUIRE _A_PINB
//   83 #pragma diag_default=Ta006
//   84
//   85 #pragma vector=TIMER0_OVF_vect

        RSEG CODE:CODE:NOROOT(1)
//   86 __interrupt __raw void TASK3dispatch(void)
TASK3dispatch:
//   87 {
//   88   if (TASK3_LOCK) return;
        SBIC    0x1E, 0x01
        RJMP    ??TASK3dispatch_0
//   89   TASK3_LOCK=1;
        SBI     0x1E, 0x01
//   90   DISABLE_TASK2();
        CBI     0x1F, 0x03
//   91   __enable_interrupt();
        SEI
//   92   ((void(*)(void))TASK3)();  
        RCALL   TASK3
//   93   __disable_interrupt();
        CLI
//   94   TASK3_LOCK=0;
        CBI     0x1E, 0x01
//   95   if (TASK2_LOCK) return;
        SBIC    0x1E, 0x00
        RJMP    ??TASK3dispatch_0
//   96   if (TASK2_WAKEUP) ENABLE_TASK2();
        SBIC    0x1E, 0x02
        SBI     0x1F, 0x03
??TASK3dispatch_0:
        RETI
        REQUIRE _A_EECR
        REQUIRE _A_GPIOR0
//   97 }
//   98
//   99 #pragma vector=INT0_vect

        RSEG CODE:CODE:NOROOT(1)
//  100 __interrupt void TASK4(void)
TASK4:
//  101 {
        ST      -Y, R17
        ST      -Y, R16
        IN      R17, 0x3F
//  102   //Тут тоже колдовство, запрещаем все прерывания, например
//  103   TIMSK0=0;
        LDI     R16, 0
        STS     110, R16
//  104   //Запрещаем и TASK2
//  105   DISABLE_TASK2();
        CBI     0x1F, 0x03
//  106   __enable_interrupt();
        SEI
//  107   //Чего-то делаем, тут еще бывает INT1, но это уже не суть
//  108   __disable_interrupt();
        CLI
//  109   if (PINB_Bit1) WAKEUP_TASK2(); //К примеру
        SBIC    0x03, 0x01
        SBI     0x1E, 0x02
//  110   TIMSK0=1<<TOV0;
??TASK4_0:
        LDI     R16, 1
        STS     110, R16
//  111   if (TASK3_LOCK) return;
        SBIC    0x1E, 0x01
        RJMP    ??TASK4_1
//  112   if (TASK2_LOCK) return;
        SBIC    0x1E, 0x00
        RJMP    ??TASK4_1
//  113   if (TASK2_WAKEUP) ENABLE_TASK2();
        SBIC    0x1E, 0x02
        SBI     0x1F, 0x03
??TASK4_1:
        OUT     0x3F, R17
        LD      R16, Y+
        LD      R17, Y+
        RETI


В принципе, из-за того, что управление прерыванием доступно через SBI/CBI время нахождения в состоянии с запрещенным прерыванием даже уменьшилось... Красота только пропала wink.gif


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
galjoen
сообщение May 21 2008, 06:58
Сообщение #54


Знающий
****

Группа: Свой
Сообщений: 841
Регистрация: 10-05-07
Из: Чебоксары (Россия)
Пользователь №: 27 640



Цитата(Rst7 @ May 21 2008, 09:48) *
Код
#pragma vector=TIMER0_OVF_vect
__interrupt __raw void TASK3dispatch(void)
{
  if (TASK3_LOCK) return;
  TASK3_LOCK=1;
  DISABLE_TASK2();
  __enable_interrupt();
  ((void(*)(void))TASK3)();  
  __disable_interrupt();
  TASK3_LOCK=0;
  if (TASK2_LOCK) return;
  if (TASK2_WAKEUP) ENABLE_TASK2();
}

Не совсем понял вот этот кусок, поэтому м.б. задам глупый вопрос.
Код
  if (TASK3_LOCK) return;
  TASK3_LOCK=1;

Это видимо антирекурсия, так?
Почему вы, любитель красоты в программировании (я наверное такой-же) использовали для этого лишний бит (#define TASK3_LOCK GPIOR0_Bit1), а не сам бит разрешения прерывания TOIE0 из регистра TIMSK? Это из-за того, что в вашем процессоре он не доступен командами cbi, sbic и поэтому требует вспомогательного регистра (и его сохранения) в т.ч. для проверки в прерывании INT0? Зато прерывания от таймера вообще возникать не будут - уменьшение времени нахождения с запрещёнными прерываниями ну и красота.
Go to the top of the page
 
+Quote Post
SasaVitebsk
сообщение May 21 2008, 07:15
Сообщение #55


Гуру
******

Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521



В принципе предложений накидали. smile.gif Обсуждать подход автора, считаю глупым, так как он к нам за этим не обращался, к тому же постановка вопроса близка и понятна мне.

В XMEGA будет проще данную проблему решать. smile.gif
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение May 21 2008, 07:23
Сообщение #56


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(SasaVitebsk @ May 21 2008, 10:15) *
Обсуждать подход автора, считаю глупым, так как он к нам за этим не обращался, к тому же постановка вопроса близка и понятна мне.

А поговорить? smile.gif


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Rst7
сообщение May 21 2008, 07:37
Сообщение #57


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
Зато прерывания от таймера вообще возникать не будут - уменьшение времени нахождения с запрещёнными прерываниями ну и красота.


В общем итоге - с запрещением через TIMSK хуже.

Цитата
В XMEGA будет проще данную проблему решать.


А то, там костыль есть для генерации эвентов вручную. О нас подумали wink.gif

Цитата
А поговорить?


Неси литру, поговорим smile.gif


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post
sKWO
сообщение May 21 2008, 08:21
Сообщение #58


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Цитата(Rst7 @ May 21 2008, 08:48) *
В принципе, из-за того, что управление прерыванием доступно через SBI/CBI время нахождения в состоянии с запрещенным прерыванием даже уменьшилось... Красота только пропала wink.gif

Это уже есть мысль. Круто
Да и не сказалбы я что красота пропала
Есть в общем над чем поломать голову и поучиться a14.gif


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
galjoen
сообщение May 21 2008, 09:30
Сообщение #59


Знающий
****

Группа: Свой
Сообщений: 841
Регистрация: 10-05-07
Из: Чебоксары (Россия)
Пользователь №: 27 640



М.б. конечно я уже надоел своим занудством, но...
Цитата(Rst7 @ May 21 2008, 11:37) *
В общем итоге - с запрещением через TIMSK хуже.

Мне вот это всё не нравится (некрасивым кажется):
Код
//   88   if (TASK3_LOCK) return; // вот это (лишних 12 тактов при возникновении прерывания от таймера при  TASK3_LOCK=1)
        SBIC    0x1E, 0x01
        RJMP    ??TASK3dispatch_0
//   89     TASK3_LOCK=1;
        SBI     0x1E, 0x01
//   90   DISABLE_TASK2();
        CBI     0x1F, 0x03
//   91   __enable_interrupt();
        SEI
//   92   ((void(*)(void))TASK3)(); // и ОСОБЕННО это (3+4=7 тактов лишних при КАЖДОМ вызове)
        RCALL   TASK3
//   93   __disable_interrupt();
        CLI
//   94   TASK3_LOCK=0;
        CBI     0x1E, 0x01
//   95   if (TASK2_LOCK) return;
        SBIC    0x1E, 0x00
        RJMP    ??TASK3dispatch_0
//   96   if (TASK2_WAKEUP) ENABLE_TASK2();
        SBIC    0x1E, 0x02
        SBI     0x1F, 0x03
??TASK3dispatch_0:

Всё это ведь сделано что-бы регистры при возникновении прерывания при TASK3_LOCK=1 не сохранялись. А если в прерывании от таймера __interrupt void использовать, а там и TASK3_LOCK=1 устанавливать (для INT0), и TIMSK запрещать (всего 3 такта лишних)? Вроде по всем параметрам лучше. Ну а главное красивее smile.gif .
Go to the top of the page
 
+Quote Post
Rst7
сообщение May 21 2008, 09:38
Сообщение #60


Йа моск ;)
******

Группа: Модераторы
Сообщений: 4 345
Регистрация: 7-07-05
Из: Kharkiv-city
Пользователь №: 6 610



Цитата
Мне вот это всё не нравится (некрасивым кажется):


Ну попробуйте переделать. Рыба, которую я привел - она компилируется...


--------------------
"Практика выше (теоретического) познания, ибо она имеет не только достоинство всеобщности, но и непосредственной действительности." - В.И. Ленин
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 19:15
Рейтинг@Mail.ru


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