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

 
 
4 страниц V  < 1 2 3 4 >  
Reply to this topicStart new topic
> Работа с переменными в прерывании и основном теле, жутко неудобно выходит
_Pasha
сообщение Oct 8 2015, 16:55
Сообщение #31


;
******

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



Цитата(ViKo @ Oct 8 2015, 12:31) *
Читать и сравнивать целиком 2-байтовый указатель - неоптимально. Можно прочитать старший байт, затем младший, затем снова старший, и если он не изменился, значит, 2-байтовое число верное.

Может и так rolleyes.gif
Но погружение на уровень байтов - не кроссплатформенно. Тут кому что важнее
Go to the top of the page
 
+Quote Post
Alexashka
сообщение Oct 8 2015, 18:17
Сообщение #32


Практикующий маг
******

Группа: Свой
Сообщений: 3 634
Регистрация: 28-04-05
Из: Дубна, Моск.обл
Пользователь №: 4 576



Цитата(jcxz @ Oct 8 2015, 13:09) *
Есть вероятность, что Ваше ПО сейчас работает, а через 10 секунд - есть вероятность, что не работает...

Да это понятно, только объясните чем этот механизм отличается от предложенного с разделением доступа?
Go to the top of the page
 
+Quote Post
jcxz
сообщение Oct 9 2015, 03:18
Сообщение #33


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Alexashka @ Oct 9 2015, 00:17) *
Да это понятно, только объясните чем этот механизм отличается от предложенного с разделением доступа?

Тем, что если делать корректно, то работает 100%-но.
Go to the top of the page
 
+Quote Post
ASN
сообщение Oct 9 2015, 06:05
Сообщение #34


Местный
***

Группа: Свой
Сообщений: 459
Регистрация: 15-07-04
Из: g.Penza
Пользователь №: 326



Alexashka
Так и не понял, почему запрет прерываний так критичен?
Аудиосигнал - это 8 кГц. Тактовая частота современного ОМЭВМ с архитектурой 8051 - не менее 25 МГц. Цикл команды работы с внешней памятью - не более 5 тактов.
То есть, количество команд между отсчётами (в самом худшем случае) - более 500.
Почему добавление тройки команд так сильно "тормозит" обработку прерываний?
Может лучше, как Вам и предложили, работать полными буферами по 256 байт? Тогда все операции будут байтовые и вызываться обработчик будет в 256 раз реже.
Go to the top of the page
 
+Quote Post
Valentine Logino...
сообщение Oct 9 2015, 06:51
Сообщение #35


Частый гость
**

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



Вообще долгая работа с данными в прерывании плохо. В прерывании будим поток (для однопоточки меняем состояние машины состояний), выходим из прерывания и выполняем всю работу сразу.
Если же работы с данными мало и это не раздувает прерывание, то использование критических секций не должно создавать каких-либо проблем.
Go to the top of the page
 
+Quote Post
Alexashka
сообщение Oct 9 2015, 07:40
Сообщение #36


Практикующий маг
******

Группа: Свой
Сообщений: 3 634
Регистрация: 28-04-05
Из: Дубна, Моск.обл
Пользователь №: 4 576



Цитата(Valentine Loginov @ Oct 9 2015, 10:51) *
Вообще долгая работа с данными в прерывании плохо. В прерывании будим поток (для однопоточки меняем состояние машины состояний), выходим из прерывания и выполняем всю работу сразу.
Если же работы с данными мало и это не раздувает прерывание, то использование критических секций не должно создавать каких-либо проблем.

Я хочу понять логику работы с семафорами. Допустим в прерывании читаю из буфера 1 байт, это действие приоритетное, его откладывать нельзя. В основном теле я пишу в буфер тоже по 1 байту за раз. Также в прерывании и в основном теле мне нужно знать сколько байт в буфере имеется и не произошло ли переполнение (для этого мне нужно обращаться к указателям головы и хвоста буфера, что собственно и хотелось бы сделать без использования запретов прерываний). Как в таком случае нужно задействовать семафоры?

Цитата(ASN @ Oct 9 2015, 10:05) *
Alexashka
Так и не понял, почему запрет прерываний так критичен?
Аудиосигнал - это 8 кГц. Тактовая частота современного ОМЭВМ с архитектурой 8051 - не менее 25 МГц. Цикл команды работы с внешней памятью - не более 5 тактов.
То есть, количество команд между отсчётами (в самом худшем случае) - более 500.
Почему добавление тройки команд так сильно "тормозит" обработку прерываний?

Просто не хочу использовать этот метод вот и все. Хочу чтобы была единая логика в независимости от источника прерываний и типа переменных, потому что функции работы с кольцевым буфером использую постоянно и в разных задачах и каждый раз приходится их допиливать-перепиливать, и это уже достало.
Да и к тому же сейчас у меня частота 22050 Гц, потом планирую добавить буфер для ЦАП, который будет писать в него на частоте 200кГц и задержки будут совсем нежелательны. Дело не в том, что я не успею вывести очередной отсчет, а в том что будет дрожание момента вывода отсчета, отсюда искажения в спектре.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Oct 9 2015, 08:33
Сообщение #37


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



QUOTE (Alexashka @ Oct 9 2015, 10:40) *
Я хочу понять логику работы с семафорами.

Лучше поймите, как стоить системы БЕЗ семафоров. Семафоры это костыли. Я как-то о семафорах не думал - ну пользовал и пользовал. А в году так 2004 попалась в руки FreeRTOS, где семафоры сделаны были, как макросы на очередях. Подумал, какой ужас, еще раз подумал и понял, что лишняя сущность.



--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Alexashka
сообщение Oct 9 2015, 13:09
Сообщение #38


Практикующий маг
******

Группа: Свой
Сообщений: 3 634
Регистрация: 28-04-05
Из: Дубна, Моск.обл
Пользователь №: 4 576



Цитата(zltigo @ Oct 9 2015, 12:33) *
Лучше поймите, как стоить системы БЕЗ семафоров.

А как бы Вы сделали? rolleyes.gif
Go to the top of the page
 
+Quote Post
rudy_b
сообщение Oct 9 2015, 13:19
Сообщение #39


Знающий
****

Группа: Свой
Сообщений: 888
Регистрация: 25-09-08
Из: Питер
Пользователь №: 40 458



Цитата(Alexashka @ Oct 3 2015, 22:40) *
Добрый вечер sm.gif
Что имеем: 8 битный проц, программа в прерывании читает из кольцевого буфера, указатель чтения -просто индекс массива, двухбайтное число. В основном теле мне приходит поток байт, который я контролирую (запускаю/останавливаю поток) и размещаю байты в этом же кольцевом буфере по другому указателю -указателю записи (тоже индекс массива)...

Как-то странно выглядит. Обычно все наоборот делается - приходящие байты запихиваются в буфер по прерываниям (хард) и ставится (или суммируется) флаг+(возможно) управление потоком.
Тут можно работать с указателями просто - в функции обработки прерываний другие прерывания запрещены (обычно).

А считывание из буфера идет в main loop при наличии флага (или ненулевого счетчика).
При этом все операции с указателями (и флагом) делаются в main loop с кратковременным запретом прерываний.
Есть какая-то специфика?
Go to the top of the page
 
+Quote Post
zltigo
сообщение Oct 9 2015, 13:42
Сообщение #40


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



QUOTE (Alexashka @ Oct 9 2015, 16:09) *
А как бы Вы сделали? rolleyes.gif

Я не могу ответить на вопрос, куда пришить пуговицу не видя всего костюма. Но разумный совет здесь http://electronix.ru/forum/index.php?showt...t&p=1369549


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
Alexashka
сообщение Oct 9 2015, 17:09
Сообщение #41


Практикующий маг
******

Группа: Свой
Сообщений: 3 634
Регистрация: 28-04-05
Из: Дубна, Моск.обл
Пользователь №: 4 576



Цитата(rudy_b @ Oct 9 2015, 17:19) *
Как-то странно выглядит. Обычно все наоборот делается - приходящие байты запихиваются в буфер по прерываниям (хард) и ставится (или суммируется) флаг+(возможно) управление потоком.
Тут можно работать с указателями просто - в функции обработки прерываний другие прерывания запрещены (обычно).

А считывание из буфера идет в main loop при наличии флага (или ненулевого счетчика).
При этом все операции с указателями (и флагом) делаются в main loop с кратковременным запретом прерываний.
Есть какая-то специфика?

Не ну честно, господа совершенно не желают ничего читать. Объяснял уже трижды, но каждый раз задаются одни и те же вопросы. Ладно, Вам лично объясню в четвертый раз sm.gif Данные приходят по UART, я их совершенно не напрягаясь успеваю забирать в главном цикле и складывать в кольцевой буфер. Скорость UART 230кБит. В прерывании (которое вырабатывает таймер) я что делаю - читаю из буфера одно значение (сэмпл) и тут же записываю его в регистр PCA для обновления генератора ШИМ сигнала. Частота генерации 22050. Если это делать не в прерывании, то будет совершенно очевидный джиттер. Это не обсуждается.
Поскольку частота сыпанья байтов из UART ровно 23000 в секунду, т.е чуть больше чем скорость их чтения (22050) приходится периодически прерывать этот поток отсылая в компУтер команду "ПОГОДИ!", когда буфер чутка освободится я шлю команду "ПЕРЕДАВАЙ!"
Ясно, что можно обработку обоих потоков сделать в прерывании, но мне удобней работать с UART по опросу флагов. Да и вообще дело не в данной конкретной задаче, а просто назрело - захотел переделать логику работы с буферами чтобы было удобнее, тут уже было озвучено много разных вариантов, но у всех у них есть достоинства и недостатки sm.gif
Так что обсуждение еще продолжается.
Да, помимо всего прочего много нового для себя узнал, за что всем коллегам большое спасибо a14.gif
Go to the top of the page
 
+Quote Post
ViKo
сообщение Oct 9 2015, 18:19
Сообщение #42


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Так зачем "чутка освободится..."? Сделайте 2 буфера. В один принимаете, из другого кидаете в ШИМ. Когда в том, что в ШИМ, данные закончатся, переключаетесь на тот, в который принимали. Он уже будет весь забит. И т.д. По-моему, это называется "двойная буферизация". А принимайте тоже по прерыванию, только приоритет задайте ниже, чем у таймера выкидывания. И... это, зачем большие буфера? sm.gif sm.gif
Go to the top of the page
 
+Quote Post
rudy_b
сообщение Oct 9 2015, 23:08
Сообщение #43


Знающий
****

Группа: Свой
Сообщений: 888
Регистрация: 25-09-08
Из: Питер
Пользователь №: 40 458



Цитата(ViKo @ Oct 9 2015, 21:19) *
Так зачем "чутка освободится..."? Сделайте 2 буфера. В один принимаете, из другого кидаете в ШИМ...
...А принимайте тоже по прерыванию, только приоритет задайте ниже, чем у таймера выкидывания. И... это, зачем большие буфера? sm.gif sm.gif

Все так, но не нужно два буфера - нужен только один - кольцевой.
И, как и предложено, и принимать и считывать по прерываниям. Если они одного уровня - друг друга прерывать не будут, обычно на 8-ми битках так сделано. Приоритет работает только при одновременном возникновении двух запросов - вот тогда первым будет более приоритетный.
Т.е. при работе с указателями вообще никаких проблем не будет.

Большой размер буфера иногда нужен при работе с писюком для разравнивания данных - он иногда любит отключать задачу чуть не на секунду.

Джиттера все равно не избежать, можно только снизить его до минимума, если сделать прерывание считывания более высокоуровневым (т.е. разрешить ему прерывать прерывание записи).
Тогда есть два варианта. Можно аккуратно работать с указатем записи (кратковременный запрет прерываний) - но это джиттер, хоть и малый.
А можно и без запрета прерываний.
За буфером следит более высокоуровневое прерывание и оно, при приближении к заполнению, ставит (и снимает, с командой продолжения приема или иначе) флаг, который более низкоприоритеное прерывание использует для остановки входного потока.
Указатель чтения оно меняет как ему вздумается (это его параметр), а вот указателей записи - два.
Один из них использует только низкоприоритетное прерывание, а второй - более высокоприоритетное.
Периодически происходит синхронизация этих указателей в старшем прерывании - для определения остатка свободного места в буфере. Тут может возникнуть болтанка и нужен запас свободного места в буфере на максимальное число неудачных попыток синхронизации (ну и плюс запас).
Для синхронизации, младшее прерывание меняет свой указатель поэтапно, каждый раз выставляя и снимая бит валидности в отдельной переменной.
Т.е., перед изменением оно сначала снимает бит валидности, затем меняет указатель, затем ставит бит валидности. Это можно делать и для каждого байта по отдельности.
Старший приоритет синхронизирует свой указатель только если стоит бит валидности.
Это, практически, критическая секция, но специфическая, с пропуском, но без зависания.

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

Можно использовать и несколько фокусов типа - при неудачной синхронизации инкрементировать указатель приема в старшем прерывании (это снизит болтанку буфера) и т.п.

Заморочно, конечно, но джиттер будет минимален.

Аналогичное взаимодействие можно организовать и между main loop и прерыванием считывания. Тогда будет только одно прерывание и джиттер будет меньше.
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Oct 10 2015, 03:51
Сообщение #44


Гуру
******

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



Какие компоненты в систему заложишь, так она и поплывет.

PC + восьмибитник + требование к джиттеру = бульк

Извините за ОФФ.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
Alexashka
сообщение Oct 10 2015, 11:19
Сообщение #45


Практикующий маг
******

Группа: Свой
Сообщений: 3 634
Регистрация: 28-04-05
Из: Дубна, Моск.обл
Пользователь №: 4 576



Цитата(ViKo @ Oct 9 2015, 22:19) *
Так зачем "чутка освободится..."? Сделайте 2 буфера. В один принимаете, из другого кидаете в ШИМ. Когда в том, что в ШИМ, данные закончатся, переключаетесь на тот, в который принимали. Он уже будет весь забит. И т.д. По-моему, это называется "двойная буферизация". А принимайте тоже по прерыванию, только приоритет задайте ниже, чем у таймера выкидывания. И... это, зачем большие буфера? sm.gif sm.gif

Это не будет работать. Если один источник пишет быстрее, чем другой читает, то рано или поздно (сколько бы у вас ни было буферов) произойдет переполнение буфера. Скорости обоих процессов должны быть в среднем одинаковы.
А по поводу прерывания. Если приоритеты обоих одинаковы, то получаем джиттер в виде задержки входа в прерывание ШИМ равное по времени выполнению прерывания UART.
В случае если прерывание UART имеет меньший приоритет по сравнению с ШИМ, то будет тоже самое в плане критических секций - придется в прерывании UART временно блокировать прерывание ШИМ.

Цитата(rudy_b @ Oct 10 2015, 03:08) *
Большой размер буфера иногда нужен при работе с писюком для разравнивания данных - он иногда любит отключать задачу чуть не на секунду.

Именно поэтому использую почти всю встроенную память, а чего ее жалеть ради хорошего дела sm.gif
Цитата(rudy_b @ Oct 10 2015, 03:08) *
Джиттера все равно не избежать, можно только снизить его до минимума, если сделать прерывание считывания более высокоуровневым (т.е. разрешить ему прерывать прерывание записи).
Но тогда это будет работать также, как если UART будет в основном теле.
Цитата(rudy_b @ Oct 10 2015, 03:08) *
Тогда есть два варианта. Можно аккуратно работать с указатем записи (кратковременный запрет прерываний) - но это джиттер, хоть и малый.
Сейчас так и делаю. Причем что интересно полностью избежать запрета прерываний нельзя - его можно избежать когда в основном теле читаем переменную, изменяемую в прерывании -тут помогает метод двух чтений, который предложил Pasha. А вот в случае когда в прерывании читается переменная, изменяемая в основном теле (это нужно чтобы определить не нагнало ли чтение запись) этот метод не поможет.
Цитата(rudy_b @ Oct 10 2015, 03:08) *
А можно и без запрета прерываний.
...
Периодически происходит синхронизация этих указателей в старшем прерывании - для определения остатка свободного места в буфере.
...
Для синхронизации, младшее прерывание меняет свой указатель поэтапно, каждый раз выставляя и снимая бит валидности в отдельной переменной.
Т.е., перед изменением оно сначала снимает бит валидности, затем меняет указатель, затем ставит бит валидности. Это можно делать и для каждого байта по отдельности.
Старший приоритет синхронизирует свой указатель только если стоит бит валидности.
Это, практически, критическая секция, но специфическая, с пропуском, но без зависания.
...Аналогичное взаимодействие можно организовать и между main loop и прерыванием считывания.

Посмотрите, что я писал в сообщении #27, но то мое предложение оплевали и посоветовали выкинуть в утиль sm.gif.
Это не сложно, но опять-таки не универсальное решение, потому как требует персональной корректировки функций по работе с кольцевым буфером под конкретную задачу.

Цитата(Dog Pawlowa @ Oct 10 2015, 07:51) *
Какие компоненты в систему заложишь, так она и поплывет.

PC + восьмибитник + требование к джиттеру = бульк

Не согласен с Вами. Восьмибитник отлично справляется, да у него нет канала DMA который можно накрутить в ШИМ имея какойнибудь Кортекс, но для моей задачи вполне хватает. И потом эта работа -мое хобби, а мне 8-битники нравятся гораздо больше, чем 32разрядные монстры с DMA контроллерами, ускорителями памяти и прочим и прочим.
Имеющихся аппаратных возможностей контроллера более чем достаточно для этой задачи.
Go to the top of the page
 
+Quote Post

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

 


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


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