Easyelectronics.ru

Электроника для всех
Текущее время: 01 окт 2020, 18:37

Часовой пояс: UTC + 5 часов



JLCPCB – Прототипы печатных плат за $2/5шт. два слоя. $5/5шт. четыре слоя
Крупнейший производитель печатных плат и прототипов. Более 600000 клиентов и свыше 10000 заказов в день!
Получите скидку на почтовую отправку при первом заказе в JLCPCB!

Начать новую тему Ответить на тему  [ Сообщений: 98 ]  На страницу Пред.  1, 2, 3, 4  След.
Автор Сообщение
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 02 май 2016, 17:18 
Старожил
Аватара пользователя

Зарегистрирован: 11 апр 2016, 18:04
Сообщения: 3571
Откуда: Китай, Пекин
Цитата:
wr еще не 0, но уже и не то, что было раньше.

А Вы упорный. ) главное чтобы wr было НЕ больше rd

Цитата:
Т.е. rd != wr == есть данные.
нет rd < wr есть данные.

_________________
unirail.org


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 02 май 2016, 17:24 
Старожил
Аватара пользователя

Зарегистрирован: 29 янв 2010, 15:41
Сообщения: 1127
Откуда: Германия
Правильно ли я понимаю, что операция RBUF_MASK(RBUF) & (RBUF).wr обеспечивает цикличность?
Но в таком разе размер буфера должен быть кратным степени двойки? Т.е. я не могу сделать буфер длинной, скажем 305 байт, что иногда очень даже бывает нужным ;-)

_________________
Мои поделки
http://www.fun-electronic.net/


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 02 май 2016, 17:31 
Старожил
Аватара пользователя

Зарегистрирован: 11 апр 2016, 18:04
Сообщения: 3571
Откуда: Китай, Пекин
Цитата:
Правильно ли я понимаю

правильно.

#define RBUF_INIT(TYPE, LENPOW2 ) volatile struct { \

Цитата:
305 байт


хочется странного? функция этого буфера в другом. сглаживать .

_________________
unirail.org


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 02 май 2016, 17:42 
Старожил
Аватара пользователя

Зарегистрирован: 29 янв 2010, 15:41
Сообщения: 1127
Откуда: Германия
cheblin писал(а):
Цитата:
wr еще не 0, но уже и не то, что было раньше.

А Вы упорный. ) главное чтобы wr было НЕ больше rd

Цитата:
Т.е. rd != wr == есть данные.
нет rd < wr есть данные.

Да, я упорный :) Хе, хе. До сих пор мы рассмотрели сценарий записи из основного цикла, и чтения в прерывании. И это ваше замечание сюда очень хорошо вписывается....

А теперь ;-) давайте рассмотрим обратный процесс.
Чтения из основного цикла и записи в прерывании (у нас же не однонаправленный поток данных, я надеюсь)
Итак, переменные хранятся в памяти. Для их сравнения проц грузит их в регистры (ну насколько я знаю ассемблер, команда CMP регистры сравнивает а не ячейки памяти).
Хе хе хе.
Значит, загрузил он одну переменную (кстати, хрен его знает какую именно, это дано на откуп оптимизатора, насколько я знаю), и тут пришло прерывание, и обнулило их обе :), и одну даже увеличило на 1. Вышли из прерывания, загрузили другую переменную в регистр. Сравниваем.... старое значение одной с новым значением другой. Ну вот и приехали, собсно.
Или я опять что то упустил?

Я почему такой упорный :) Просто я тут уже лет 7 программлю коммуникации для празных проектов. В основном по УАРТ. И тут есть у меня кольцевой буфер. Так вот там я таких приколов насмотрелся....

Цитата:
хочется странного?

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

_________________
Мои поделки
http://www.fun-electronic.net/


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 02 май 2016, 17:45 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2795
Откуда: Санкт-Петербург
Imho не стОит запариваться насчёт запрета прерываний на десяток тактов. Расплата за отказ от этого - взрыв мозга (ну, вы же в курсе про lock-free алгоритмы и грабли с ними, начиная с ABA problem?) и усложнение/замедление кода.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 02 май 2016, 18:38 
Старожил
Аватара пользователя

Зарегистрирован: 06 ноя 2013, 16:07
Сообщения: 711
Откуда: Германия
rd==0x000000FF
wr==0x00000100
размер - 32

Начинаем читать и доходим до rd++. В регистрах 0x00000100, в памяти все еще 0x000000FF. Сохраняем по-байтово, например справа налево. Получаем на первом шаге 0x00000000 в памяти. Приходит прерывание, пытается записать один байт и видит, что буфер заполнен (wr-rd>31) - выкидывает принятый байт. Минус еще одна ракета.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 02 май 2016, 18:41 
Старожил
Аватара пользователя

Зарегистрирован: 11 апр 2016, 18:04
Сообщения: 3571
Откуда: Китай, Пекин
Цитата:
Или я опять что то упустил?

может произойти 2 варианта

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

и это приемлемо.

2) ошибочно посчитать, что в буфере данные есть.... а вот это уже очень плохо... подозреваю что ситуацию можно будет подправить гарантировав очередность доступа доступа к rd, wr например в локальную переменную записав значение rd и потом сравнив c wr напрямую.

_________________
unirail.org


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 02 май 2016, 18:56 
Старожил
Аватара пользователя

Зарегистрирован: 11 апр 2016, 18:04
Сообщения: 3571
Откуда: Китай, Пекин
Цитата:
выкидывает принятый байт.

при передачи данных данные теряются, искажаются... удивительно, но это норма.

вышестоящие уровни обязаны отрабатывать такую ситуацию. безо всякого краха...

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

факт потери данных по причине плохого канала, также должен быть обнаружен и передан пользователю.

он уже и примет решение... менять проводку, экранировать, заземлять, увеличивать размер буфера ...

_________________
unirail.org


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 02 май 2016, 19:06 
Старожил
Аватара пользователя

Зарегистрирован: 29 янв 2010, 15:41
Сообщения: 1127
Откуда: Германия
cheblin писал(а):
...увеличивать размер буфера ...

305 байт ;-)

_________________
Мои поделки
http://www.fun-electronic.net/


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 02 май 2016, 19:14 
Старожил
Аватара пользователя

Зарегистрирован: 11 апр 2016, 18:04
Сообщения: 3571
Откуда: Китай, Пекин
Цитата:
не стОит запариваться насчёт запрета прерываний на десяток тактов

например в моём Scala мирке конструкция типа while(1){} - почти как деление на ноль - взрыв мозга, а в микроконтроллере норма..

и в этой новой для себя реальности, я пытаюсь нащупать рамки допустимого..... придушить прерывания - это универсальное решение лежащее на поверхности... так делают все встроенные RTOS - ибо универсально.

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

можно ли из этого что то выжать? думаю....

_________________
unirail.org


Последний раз редактировалось cheblin 02 май 2016, 20:34, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 02 май 2016, 19:34 
Старожил

Зарегистрирован: 20 мар 2013, 11:27
Сообщения: 5358
Интересный вариант
Я такую же задачу решил для stm8/avr8, универсальный код
Так же использую для uart
Буфер там одногаправленный и все работает правильно хотя атомарности нет

И как ее обеспечить на stm8 без отключения прерываний?
На avr как я понял это делается специальными атрибутами описанными в atomic.h


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 02 май 2016, 20:16 
Старожил
Аватара пользователя

Зарегистрирован: 11 апр 2016, 18:04
Сообщения: 3571
Откуда: Китай, Пекин
Цитата:
...и все работает

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

кстати помимо UART на этом же чипе у меня сейчас вертится
1)таймер PWM для управления ESC BLDC (стандатные 488Hz)
2)прерывание на ноге для получения высокочастотной 12 битной посылки с тензодатчика HX711 https://learn.sparkfun.com/tutorials/load-cell-amplifier-hx711-breakout-hookup-guide с частотой 10герц

и весь этот небольшой оркестр работает. правда скорость обмена у меня пока 9600....

_________________
unirail.org


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 02 май 2016, 20:57 
Старожил

Зарегистрирован: 27 мар 2015, 01:22
Сообщения: 1953
cheblin писал(а):
придушить прерывания - это универсальное решение лежащее на поверхности... так делают все встроенные RTOS - ибо универсально.

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

можно ли из этого что то выжать? думаю....

Есть и третий путь )
Вообще отказаться от прерываний кроме систика
http://www.safetty.net/publications/pttes

_________________
mcu.goodboard.ru


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 02 май 2016, 21:00 
Старожил
Аватара пользователя

Зарегистрирован: 06 ноя 2013, 16:07
Сообщения: 711
Откуда: Германия
Сделать это можно и даже не сложно. Например, если ограничить длину до 255 байт. Можно и больше, но тогда чуть сложнее. Но почему-то абсолютное большинство реализаций не работают совершенно.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 02 май 2016, 21:06 
Старожил
Аватара пользователя

Зарегистрирован: 11 апр 2016, 18:04
Сообщения: 3571
Откуда: Китай, Пекин
vt340 писал(а):
Есть и третий путь )

о! спасибо, почитать я люблю. на первый взгляд правда похоже на "как из палок и верёвок сделать RTOS за 24 часа" да и год выпуска
Цитата:
First published in Great Britain in 2001
кагэбы намекает, но (!) ещё раз спасибочки!

_________________
unirail.org


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 02 май 2016, 21:08 
Старожил

Зарегистрирован: 19 мар 2013, 19:37
Сообщения: 2795
Откуда: Санкт-Петербург
axill, то, что в atomic.h - тоже через отключение прерываний. Просто поудобнее, чем явно писать cli/sei - гарантирует выполнение парного sei.

cheblin, imho овчинка не стоит выделки. Придётся много думать только ради того, чтобы получить решение для частного случая (даже ваш вариант - это два разных случая: в прерывании reader или writer). А выигрыш? В лучшем случае - уменьшение возможной latency для прерывания до микросекунды. Если это критично - не очень понятно, зачем вам FIFO.

vt340, путь хорош, но сейчас мы произнесём сакральную аббревиатуру из двух букв и призовём в тред Сами Знаете Кого :-)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 02 май 2016, 22:55 
Старожил
Аватара пользователя

Зарегистрирован: 30 янв 2014, 18:09
Сообщения: 647
Откуда: Киев
Для STM8 и средней модели памяти сохранение или инкрементирование 16-ти битового числа - одна операция. Так что часть проблем с прерываниями отпадает.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 03 май 2016, 10:38 
Старожил
Аватара пользователя

Зарегистрирован: 11 апр 2016, 18:04
Сообщения: 3571
Откуда: Китай, Пекин
Цитата:
сохранение или инкрементирование 16-ти битового числа - одна операция.


угу, нашел об этом в PDF файле в комплекте с IAR

PROTECTING SIMULTANEOUSLY ACCESSED VARIABLES

Variables that are accessed asynchronously, for example by interrupt routines or by code
executing in separate threads, must be properly marked and have adequate protection.
The only exception to this is a variable that is always read-only.
To mark a variable properly, use the volatile keyword. This informs the compiler,
among other things, that the variable can be changed from other threads. The compiler
will then avoid optimizing on the variable (for example, keeping track of the variable in registers), will not delay writes to it, and be careful accessing the variable only the
number of times given in the source code.

For sequences of accesses to variables that you do not want to be interrupted, use the
__monitor keyword. This must be done for both write and read sequences, otherwise
you might end up reading a partially updated variable. Accessing a small-sized
volatile variable can be an atomic operation,
but you should not rely on it unless you
continuously study the compiler output. It is safer to use the __monitor keyword to
ensure that the sequence is an atomic operation.

ладно, фиг с ним.

_asm( "push a\n pop cc\n ", state );

хотя нет. это глушит все прерывания тотально, а мне нужно придушить вполне определенное, UART например.

Код:
UART1_ITConfig(UART1_IT_RXNE_OR, DISABLE);
bla-bla-blah....
UART1_ITConfig(UART1_IT_RXNE_OR, ENABLE);


да, это выглядит наиболее рационально.

Спасибо ВСЕМ за участие!

_________________
unirail.org


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 03 май 2016, 12:38 
Старожил
Аватара пользователя

Зарегистрирован: 24 июл 2012, 13:54
Сообщения: 856
Позволю себе поделиться своим буфером.
Он не атомарный. За атомароность отвечает вызывающий код.

Show ring_head.h

Show ring.h


Последний раз редактировалось elisey 03 май 2016, 16:50, всего редактировалось 1 раз.
Большие листинги нужно прятать под спойлер


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 03 май 2016, 17:42 
Старожил
Аватара пользователя

Зарегистрирован: 11 апр 2016, 18:04
Сообщения: 3571
Откуда: Китай, Пекин
относительно гарантирования очередности выполнения операций.
да, магия volatile спасает таки мой код. гарантируя очерёдность! долой запреты прервыаний! :)

http://blog.regehr.org/archives/28
Show

_________________
unirail.org


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 03 май 2016, 18:12 
Старожил
Аватара пользователя

Зарегистрирован: 24 июл 2012, 13:54
Сообщения: 856
Что-то как-то идею не уловил. Как оно сделает запись в буффер атомарной операцией?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 03 май 2016, 18:18 
Старожил

Зарегистрирован: 05 дек 2015, 16:56
Сообщения: 315
А почему вы этот буфер назвали циклическим(кольцевым)? Ведь он не работает как кольцо.
Допустим в процессе приёма RW перепрыгнет границу и начнёт указывать на 0-й элемент. RD ещё не успел дочитать данные и указывает к примеру на 10-й элемент. Ничто не мешает ни RD дочитать ранее принятые данные, ни RW продолжать приём и писать в элементы 0..9. Как собственно и должен был бы работать кольцевой буфер.
Но не в вашем случае. Ваш буфер заклинит как только будет пересечена граница массива.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 03 май 2016, 18:20 
Старожил
Аватара пользователя

Зарегистрирован: 24 июл 2012, 13:54
Сообщения: 856
Вообще, можно построить буффер без запрета прерываний... Но... Там накладных расходов получается столько, что запрет прерываний как-то красивей смотрится.

И потом, если отключать не все прерывания, а только прерывания по RX, то... мы при этом даже вообще ничего не теряем. Ибо, всё равно придется ждать, пока завершиться работа с буфером, чтобы положить туда новые данные.

Я у себя пока запрещаю прерывания глобально... Но, буду делать ревизию, перейду на одиночный запрет.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 03 май 2016, 18:30 
Старожил
Аватара пользователя

Зарегистрирован: 29 янв 2010, 15:41
Сообщения: 1127
Откуда: Германия
Gipsy писал(а):
А почему вы этот буфер назвали циклическим(кольцевым)? Ведь он не работает как кольцо.
Допустим в процессе приёма RW перепрыгнет границу и начнёт указывать на 0-й элемент. RD ещё не успел дочитать данные и указывает к примеру на 10-й элемент. Ничто не мешает ни RD дочитать ранее принятые данные, ни RW продолжать приём и писать в элементы 0..9. Как собственно и должен был бы работать кольцевой буфер.
Но не в вашем случае. Ваш буфер заклинит как только будет пересечена граница массива.

Тут RBUF_MASK(RBUF) & (RBUF).wr обеспечивает цикличность.
Единственно - размер буфера должен быть кратным степени двойки. Иначе да - заклинит.

_________________
Мои поделки
http://www.fun-electronic.net/


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Циклический(кольцевой) буфер.
СообщениеДобавлено: 03 май 2016, 18:40 
Старожил
Аватара пользователя

Зарегистрирован: 24 июл 2012, 13:54
Сообщения: 856
Gipsy
Оно будет работать... Но таки может загнуться :), хотя и в очень невероятном случае...


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 98 ]  На страницу Пред.  1, 2, 3, 4  След.


Часовой пояс: UTC + 5 часов


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB