Перейти к содержанию
    

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

Еще как происходит - я контролирую переполнение и исчерпание очереди (соотв. ловушки/логи)!

Если в задаче в процессе извлечения свежего байта из очереди пришел еще один новый байт,

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

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

 

Именно это я и описал выше.

У меня очередь сделана в виде шаблона, всего один параметр - тип данных.

При создании экземпляра очереди ей передается ссылка на класс Interrupt, в котором есть два обязательным метода disable и enable.

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

 

Семафор это головная боль ОС.
При чем тут это?

Я лишь привел пример с осью, как наиболее универсальный.

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

Способ оповещения основного кода в данном случае не имеет никакого значения. Отклоняемся от темы )))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Защищённый режим: стек для потоков psp, стек для прерываний msp.

Поток не имеет прямого доступа к части системных регистров.

Приоритет SVC - 0.

Пользовательские прерывания 1~14.

Системный таймер, и таймер реального времени =15.

Любой поток и прерывание может вызвать SVC без разрушения стека. Системный таймер и таймер реального может прервать любое прерывание, все изменения при этом будут скидываться стек прерываний, и восстанавливаться до первоначального вида совершенно автоматически.

Кукла для всех прерываний не требуется!!!

 

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

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

При чем тут это?

Я лишь привел пример с осью, как наиболее универсальный.

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

Способ оповещения основного кода в данном случае не имеет никакого значения. Отклоняемся от темы )))

Это как раз причина по которой у меня с ОС не происходит, а с "неким флажком" происходит. Поясняю:

 

Если работа задачи, которая извлекает данные из очереди управляется семафором через ОС, то "недополнения" очереди возникнуть просто не может - задача блокируется и ожидает когда появятся данные. Поэтому указатель "хвоста" в полной безопасности.

 

Теперь про голову - данные из UART выгребаем в прерывании, в этом же прерывании увеличиваем счетчик семафора и добавляем в очередь. Чтобы избежать переполнения очереди достаточно проверить счетчик семафора. Вот собственно и все. Счетчик семафора это проблема ОС, остальное (очередь и указатели на голову/хвост) в полной безопасности.

 

Если интересно, как сделана у меня в ОС работа с семафорами, то через те же LDREX/STREX :) Правда это если не касаться вопросов переключения задач и системных вызовов, но то уже точно другая тема.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Это как раз причина по которой у меня с ОС не происходит, а с "неким флажком" происходит. Поясняю:

Да при чем тут семафор, ось, флажки и т.п.???

Я говорю про совсем другое - манипулирование индексами головы, хвоста и изменяемых данных которые должны меняться в едином непрерывном блоке кода.

Если обработчик прерываний разорвет эту цепочку в самом неподходящем месте, то рано или поздно произойдет HF.

 

 

Приоритет SVC - 0.

Пользовательские прерывания 1~14.

Системный таймер, и таймер реального времени =15.

Поменять шило на мыло?

По вашей логике получится, что пока этот приоритетный SVC не отработает, ни одно более важное аппаратное прерывание не пройдет.

SVC с таким высоким приоритетом, вызываемые из других менее приоритетных прерываний по сути временно задирает их собственный приоритет, который был "ниже плинтуса", отбирая "право голоса" у более приоритетных прерываний.

На лицо - инверсия приоритетов. С чем боролись на то и напоролись. Ни чем не лучше глобальной критической секции (запрет/разрешение всех прерываний).

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я говорю про совсем другое - манипулирование индексами головы, хвоста и изменяемых данных которые должны меняться в едином непрерывном блоке кода.

Если обработчик прерываний разорвет эту цепочку в самом неподходящем месте, то рано или поздно произойдет HF.

От же ж...ну как Вам еще объяснить. Читайте внимательно и думайте:

1. Указатель на голову (куда добавляются данные) он используется только в прерывании которое добавляет данные, только там, и больше нигде.

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

 

Синхронизация делается семафором, как и защита от переполнения/недополнения. К семафору есть доступ и у задачи, и у прерывания, но он делается через ОС.

 

Теперь понятно? Если нет, то перечитайте пожалуйста еще раз, ну или несколько раз - не знаю как объяснить иначе...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

От же ж...ну как Вам еще объяснить. Читайте внимательно и думайте:

Я про Фому, а он - про Ерему ...

 

Ясен пень, что голова и хвост изменяются в разным местах - один в фоне задач, другой - в перрывании, но !

Чтобы проверить переполнение/исчерпание, нужно контроллировать в непрерывном куске кода ОБА указателя/индекса.

Это можно делать только там, где производите изменение этих самых указателей/индексов - в прерывании и в фоне задач.

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

А в фоне задачи нужно защищать обращение к ОБОИМ указателям в некой критической секции, иначе невозможно контроллировать подобные аварийные события.

Если этого не делать, то буфер может быть переполнен/исчерпан так, что об этом невозможно будет узнать.

 

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

Чтобы положить данные в буфер в фоне задачи, нужно обращаться в непрерывном куске кода к ОБОИМ указателям. Поэтому тут нужна критическая секция или что-то подобное.

 

Синхронизация делается семафором...

Точно, я про Фому, а он - про Ерему )))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чтобы проверить переполнение/исчерпание, нужно контроллировать в непрерывном куске кода ОБА указателя/индекса.

Нет. Достаточно проверить состояние семафора.

 

А в фоне задачи нужно защищать обращение к ОБОИМ указателям в некой критической секции, иначе невозможно контроллировать подобные аварийные события.

Если этого не делать, то буфер может быть переполнен/исчерпан так, что об этом невозможно будет узнать.

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

 

Про прерывание Вы и сами написали. Так кто там про Фому :laughing:

 

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

Чтобы положить данные в буфер в фоне задачи, нужно обращаться в непрерывном куске кода к ОБОИМ указателям. Поэтому тут нужна критическая секция или что-то подобное.

Да не нужно - достаточно семафора.

 

P.S. Может быть Вы не так понимаете что такое семафор. У меня это объект синхронизации задач, который может принимать значения от 0 до некоторого MAX. Счетчик семафора показывает доступность ресурса (в данном случае кол-во данных в очереди). Задача может запросить конкретное кол-во данных или диапазон (от и до) - если нужное кол-во доступно, то задача получит запрошенное кол-во данных, если нет, то будет приостановлена, пока не будет доступно запрошенное кол-во данных.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если напрячься и таки подумать, то в задаче буфер переполнен не модет быть вообще, ибо она данные только читает. ...
Не, это - уже бесполезный спор.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не, это - уже бесполезный спор.

Конечно, ибо то, о чем я пишу работает :)

 

ОК поставим вопрос по-другому, каким образом может быть переполнен буфер в задаче, которая из него только читает?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Конечно, ибо то, о чем я пишу работает :)

И самолеты летают. Но иногда, увы, падают :(

 

ОК поставим вопрос по-другому, каким образом может быть переполнен буфер в задаче, которая из него только читает?

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

При заполнении буфера (в прерывании) нужно сравнивать ОБА указателя.

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

 

 

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

 

Я делал это несколько иначе, использовал счетчик свободного места, вообще не сравнивая указатели. Это получается несколько быстрее, но отъедает немного места в памяти.

Обращение к этому счетчику и изменение соотв. указателей, должно быть непрерывным. Иначе - HF

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И самолеты летают. Но иногда, увы, падают :(

Я тоже могу подколоть - если Вам хочется позаниматься словоблудием, то это не ко мне.

 

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

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

 

При заполнении буфера (в прерывании) нужно сравнивать ОБА указателя.

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

И в чем беда? Прочитали данные, потом произошло прерывание (в нем сравнили указатели и изменили указатель головы, кстати, в некоторых случаях можно указатели и вообще не сравнивать - достаточно кол-ва данных в очереди = значения семафора), потом (когда возвратились в задачу) изменили указатель хвоста - что мы имеем - в прерывании размер очереди был на 1 ячейку меньше, все. Никаких проблем нет. Сами же выше написали про это, а теперь "надумали" проблему там, где ее нет.

 

При обратной ситуации - задача набивает буфер для передачи через прерывание

Обратная задача решается так же, но какой смысл про нее, когда с первой не закончили.

 

Я делал это несколько иначе, использовал счетчик свободного места, вообще не сравнивая указатели. Это получается несколько быстрее, но отъедает немного места в памяти.

Обращение к этому счетчику и изменение соотв. указателей, должно быть непрерывным. Иначе - HF

Свободное место или занятое это одно и то же (свободное = размер - занятое :)), т.е. Вы говорите +- о том же, что и я писал выше и сейчас. Какой HF? Отчего? Выше я написал реальный пример, объясните где там будет HF? Даже если накосячить, то все, что может быть это потеря данных в очереди из-за переполнения.

Изменено пользователем Шаманъ

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А в фоне задачи нужно защищать обращение к ОБОИМ указателям в некой критической секции, иначе невозможно контроллировать подобные аварийные события.

И в фоновом процессе это тоже не нужно. Так как измениться в этот момент может ТОЛЬКО ОДИН указатель.

Подумайте ещё раз.

 

Если этого не делать, то буфер может быть переполнен/исчерпан так, что об этом невозможно будет узнать.

Вы похоже просто не понимаете как работают подобные кольцевые буфера... :laughing:

Инфа для размышления:

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

 

Не, это - уже бесполезный спор.

Конечно бесполезный, если Вы не хотите понимать очевидных вещей. :laughing:

Шаманъ Вам дело говорит.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И в фоновом процессе это тоже не нужно. Так как измениться в этот момент может ТОЛЬКО ОДИН указатель.

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

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

 

Если переполнение/исчерпание очереди не имеет значения для конкретного проекта, вообще не контролируется, то, конечно, можно забить на все эти критические участки кода.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я делал это несколько иначе, использовал счетчик свободного места, вообще не сравнивая указатели. Это получается несколько быстрее, но отъедает немного места в памяти.

Обращение к этому счетчику и изменение соотв. указателей, должно быть непрерывным. Иначе - HF

Вот как раз со счётчиком - это плохая реализация, так как обязательно требует критической секции.

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

Если состояние кольца читается 3-ей стороной (процессом/ядром отличным от читателя и писателя), то для этого критическая секция нужна.

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

 

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

Ну и что что станет неактуальным?

Допустим пишущий процесс считал указатель чтения и, пока он его анализировал, произошло прерывание чтения, которое убавило данных из буфера. Ну и что? От этого работа кольца не разрушится. Просто пишущий процесс в этот момент будет думать что данных в кольце больше чем уже есть. Ну и что? Это не приведёт ни к каким сбоям. Вот если-б он думал что данных меньше чем там есть - вот это бы привело к разрушению работы. Но это невозможно по алгоритму.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот как раз со счётчиком - это плохая реализация, так как обязательно требует критической секции.

Счетчик нужен для анализа переполнения/исчерпания очереди.

Если подобные события не представляют угрозы конкретному коду, то и счетчик не нужен.

И критические секции не нужны. Я с этим не спорю.

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

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

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

Самое простое - критическими секциями.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...