Только для топикстартера похоже смысл так и остался непонятным...
Тут много было всего сказано. Смысл чего? Если смысл понятия "флаг", то это вполне мне понятно. Принцип-то не сложен, в зависимости от события сигнализирует какой-то части программы: можно - нельзя, есть - нет, произошло - не произошло и т.д. И что флагом может быть все подряд ))) Главное чтобы однозначно сигнализировало о наступившем событии. Если относительно прерываний, потери информации и как не попасть в просак. То здесь я еще не вполне понимаю как правильно с этим бороться. Толи флаги ставить, то ли запрет прерываний делать, то ли флаги на флаги ставить, чтобы первые флаги писать и в прерывании и в основном цикле, без опасений То ли стараться вообще не использовать прерывания и делать в основном цикле что-то похожее на псевдомногопоточность. ))
флаги - это не переменные. флаги для того и нужны, чтобы в одном мете поставить, а в другом проверить и если поставлен, выполнить действия и сбросить флаг.
Отчего же. Переменная, пусть однобитная и объединенная с другими. И под условие задачи попадает. Как бы то ни было, даже если флаги не переменные - как их реализовать-то?
Цитата:
Именно так работают неправильно написанные кольцевые буферы.
Не сработает. Для кольцевого буфера нужно две переменных - голова и хвост. Прерывание имеет право читать голову и писать хвост, основной цикл наоборот. Конфликта записи не возникает. Более того, размер буфера в 8-битках почти никогда не превышает 8 бит, так что даже прерывания можно не блокировать, доступ останется атомарным.
Цитата:
для меня в МК вообще не существует переменных - я пишу на ассемблере и у меня есть только регистры и ячейки памяти ОЗУ.
Если под данные отводится больше одной ячейки, такой подход только все усложняет. Но опять-таки, какая разница как это назвать. Допустим, нам нужно контролировать что прошла секунда (счет в прерывании TIM0), что передана вся строка по UART и что напряжение АЦП выше порога. Из соображений экономии вы отвели под это дело биты 0,1,2 ячейки 0x0084.
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Если под данные отводится больше одной ячейки, такой подход только все усложняет.
ни чуть не усложняет.
COKPOWEHEU писал(а):
Но опять-таки, какая разница как это назвать.
совершенно верно сказано. лично мне нравится называть "параметр", и неважно, сколько ячеек он занимает. например, у меня параметр "время" - 3 ячейки памяти, часы, минуты и секунды, параметр "емкость" (аккумулятора) - 3 ячейки памяти. прочие параметры у меня все двухбайтные (2 ячейки), независимо от максимального значения параметра - для простоты доступа к ним. а на флаги я выделяю регистры, а не ячейки памяти. в одном моем проекте столько флагов, что пришлось выделить 3 регистра. выделять регистр под флаги очень удобно, так как есть команды работы с битами регистра.
_________________ Мудрость приходит вместе с импотенцией... Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Не сработает. Для кольцевого буфера нужно две переменных - голова и хвост. Прерывание имеет право читать голову и писать хвост, основной цикл наоборот. Конфликта записи не возникает. Более того, размер буфера в 8-битках почти никогда не превышает 8 бит, так что даже прерывания можно не блокировать, доступ останется атомарным.
У меня так и сделано, но тут нет записи переменной в основном коде и прерывании, а если добавлять данные в буфер могут несколько потоков, что типично для любой RTOS, где помимо этого хватает всяких мьютексов, или если размер сохраняется в отдельной переменной, что опять же типично, потому что значительная часть реализаций именно так и работает, то придется озаботиться атомарным доступом.
... Если относительно прерываний, потери информации и как не попасть в просак. То здесь я еще не вполне понимаю как правильно с этим бороться. Толи флаги ставить, то ли запрет прерываний делать, то ли флаги на флаги ставить, чтобы первые флаги писать и в прерывании и в основном цикле, без опасений То ли стараться вообще не использовать прерывания и делать в основном цикле что-то похожее на псевдомногопоточность. ))
Просто добавить в соответствующие места программ анализ флагов и соответствующую результатам анализа обработку данных. Для основной программы: Нет запроса - пробегаем мимо, есть что-то новое - исполняем (перемещая данные из промежуточного буфера в основной) и сбрасываем запрос. Для прерывания - контроль предыдущего запроса - если не обработан - пробегаем мимо если обработан - загружаем промежуточный буфер и выстваляем запрос обработки
parovoZZ, статью я понял так: если писать биты (значение) в переменную в основном цикле и также в прерывании, то может произойти потеря данных при ЗАПИСИ битов в прерывании. Автор статьи предлагает использовать запрет прерываний (атомарная операция) при записи переменной (флага) в основном цикле.
lds r16, TIM_FLAG tst r16 brne TIM_CLEARED clr r16 sts TIM_FLAG, r16 ;флаг был поднят, обрабатываем TIM_CLEARED: ;возвращаемся к выполнению
Цитата:
ни чуть не усложняет.
Вот есть значение таймера на 32 бита, есть АЦП на 16 бит, есть даже какой-то коэффициент, пришедший снаружи в формате IEE754 (float). Каждый байт в отдельности не значит ничего, значение имеют группы по 4, 2 и снова 4 байта. Еще хуже когда все это упаковано в массив структур.
Цитата:
а на флаги я выделяю регистры
Можно и так, но тогда за ними надо следить чтобы разная периферия не пыталась занять одни и те же адреса. Тем более что флаги подразумевают, что быстрой реакции не нужно, и обойтись ячейкой вполне можно. Ну там одну под события UART, вторую под SPI, третью под I2C (там одной может и не хватить).
Цитата:
для любой RTOS, где помимо этого хватает всяких мьютексов
Ну, мбютексы ведь тоже как-то реализованы, и их реализация тоже попадает под наше обсуждение.
Цитата:
или если размер сохраняется в отдельной переменной
Хранить размер буфера в переменной? А какой смысл? Я очень надеюсь, что он у вас хотя бы не в динамической памяти находится... Или вы про количество данных в буфере? Так оно вычисляется из разности между головой и хвостом за два действия.
BOB51, Вы, собственно, об этом в начале и говорили. И идея меня зацепила! Но обсуждения в теме как-то в сторону увели )) Спасибо! В общем что я из этой темы для себя вынес: 1. Писать в одну и туже переменную в основном цикле и в прерывании неправильно (неграмотно). 2. Пишем только через буфер используя флаги (семафоры, мьютексы и т.п.). Причем в буфере можно выстроить очередь запросов (данных) от прерывания. Таким образом мы и код не будем блокировать от прерываний и все прерывания будут гарантированно обработаны в их первоначальном порядке (количестве). Все правильно?
Вобщем верно. Таким способом делается "квазиавтономная" динамическая индикация - для обслуживания развертки используется таймер и буфер видеопамяти. Это система крутится сама по себе на основе прерываний по таймеру (в фоне основной программы), а в основной программе второй буфер данных и флаг запроса перезаписи. Как толькоданные готовы - флаг для "контроллера дисплея", а тот уже дождавшись нужного момента перебрасывает данные в видеопамять и затем сбрасывает флаг запроса.
Можно и так, но тогда за ними надо следить чтобы разная периферия не пыталась занять одни и те же адреса.
а как ты себе представляешь, писать на ассемблере и не следить за использованием регистров? скажу даже больше - когда пишешь на ассемблере, следить нужно не только за регистрами флагов, следить нужно за всеми регистрами.
_________________ Мудрость приходит вместе с импотенцией... Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.
1. Писать в одну и туже переменную в основном цикле и в прерывании неправильно (неграмотно). 2. Пишем только через буфер используя флаги (семафоры, мьютексы и т.п.). Причем в буфере можно выстроить очередь запросов (данных) от прерывания. Таким образом мы и код не будем блокировать от прерываний и все прерывания будут гарантированно обработаны в их первоначальном порядке (количестве). Все правильно?
Усложнять простые вещи - это, конечно, признак высшего класса.)
а как ты себе представляешь, писать на ассемблере и не следить за использованием регистров? скажу даже больше - когда пишешь на ассемблере, следить нужно не только за регистрами флагов, следить нужно за всеми регистрами.
Для кого конвенции придумали?.. Например, http://ww1.microchip.com/downloads/en/a ... c42055.pdf рекомендуют использовать r0 как временный, r1 как нулевой, r2-r17, r28, r29 как сохраняемые (при вызове функций они не меняются), r0, r18-r27, r31 как временные (подпрограмма имеет право делать с ними все что угодно). Вот и все, регистры предназначены для операций, а не для хранения данных. Разумеется, никто не мешает часть регистров зарезервировать под свои нужды. Для тех же флагов, например.
Ну, мбютексы ведь тоже как-то реализованы, и их реализация тоже попадает под наше обсуждение.
О чем и речь, в случае мьютексов тоже будет запись переменной из разных потоков и никто не говорит, что так делать нельзя.
COKPOWEHEU писал(а):
Хранить размер буфера в переменной? А какой смысл? Я очень надеюсь, что он у вас хотя бы не в динамической памяти находится... Или вы про количество данных в буфере? Так оно вычисляется из разности между головой и хвостом за два действия.
Емкость - константа, количество данных вычисляется как разность между головой и хвостом, но только если реализация именно такова, а может быть голова и размер или голова, хвост и размер, причем такие реализации можно легко найти в книгах непосредственно по эмбедду. И простой разностью можно обойтись только если емкость буфера равна степени двойки, плюс подход только с головой и хвостом чреват подводными камнями... Классический пример когда некоторые компиляторы сначала инкрементят и сохраняют tail, а потом уже пишут в buf:
И простой разностью можно обойтись только если емкость буфера равна степени двойки
Если не равняется, то вместо наложения маски будет сравнение и вычитание/сложение, вот и все.
Цитата:
а может быть голова и размер или голова, хвост и размер
Пока что я вижу только явный недостаток с тем, что к полю размера нужен доступ и при записи, и при чтении. Но вы говорите, что такие реализации есть. Чем именно они настолько хороши, что перевешивают этот недостаток?
Цитата:
плюс подход только с головой и хвостом чреват подводными камнями... Классический пример когда некоторые компиляторы сначала инкрементят и сохраняют tail, а потом уже пишут в buf
Ну так вариант с размером эту проблему не решает. И вообще, какой смысл сейчас рассматривать заведомо ошибочный код?
... Для кого конвенции придумали?.. Например, http://ww1.microchip.com/downloads/en/a ... c42055.pdf рекомендуют использовать r0 как временный, r1 как нулевой, r2-r17, r28, r29 как сохраняемые (при вызове функций они не меняются), r0, r18-r27, r31 как временные (подпрограмма имеет право делать с ними все что угодно). Вот и все, регистры предназначены для операций, а не для хранения данных. Разумеется, никто не мешает часть регистров зарезервировать под свои нужды. Для тех же флагов, например.
Регистровая модель для АВРки может быть любой - хоть под I8080 хоть под Z80 или что иное. Ограничения по "вольному" использованию возможны только для регистровых пар x, y, z и R0/R1 как потенциально используемых в командах умножения. Как вариант вот такая "заготовка" (мой "слэнг" из проектов котуинко): Спойлер
Код:
; принята базовая модель: AVR ; область ограниченного функционала ; .def = r0 ; (математика и обмен с ПЗУ/самопрограммирование) ; .def = r1 ; (математика и обмен с ПЗУ/самопрограммирование) ; .def = r2 ; зеркало SREG (ограниченный функционал) ; .def = r3 ; зеркало SPL (ограниченный функционал) ; .def = r4 ; зеркало SPH (ограниченный функционал) ; .def = r5 ; оперативные флаги (ограниченный функционал) ; .def = r6 ; оперативные флаги (ограниченный функционал) ; .def = r7 ;(ограниченный функционал) ; .def = r8 ;(ограниченный функционал) ; .def = r9 ;(ограниченный функционал) ; .def = r10 ;(ограниченный функционал) ; .def = r11 ;(ограниченный функционал) ; .def = r12 ;(ограниченный функционал) ; .def = r13 ;(ограниченный функционал) ; .def = r14 ;(ограниченный функционал) ; .def = r15 ;(ограниченный функционал) ; область полного функционала .def tmpr0 = r16 ; рабочий регистр (полный функционал) .def tmpr1 = r17 ; рабочий регистр (полный функционал) .def tmpr2 = r18 ; рабочий регистр (полный функционал) .def tmpr3 = r19 ; рабочий регистр (полный функционал) .def tmpr4 = r20 ; рабочий регистр (полный функционал) .def tmpr5 = r21 ; рабочий регистр (полный функционал) .def tmpr6 = r22 ; рабочий регистр (полный функционал) .def tmpr7 = r23 ; рабочий регистр (полный функционал) .def bpl = r24 ; "указатель базы" (полный функционал) .def bph = r25 ; "указатель базы" (полный функционал) ; Xl = r26 ; адрес сегмента Х (полный функционал) ; Xh = r27 ; адрес сегмента Х (полный функционал) ; Yl = r28 ; адрес сегмента Y (полный функционал) ; Yh = r29 ; адрес сегмента Y (полный функционал) ; Zl = r30 ; адрес сегмента Z (полный функционал ПЗУ/самопрограммирование) ; Zh = r31 ; адрес сегмента Z (полный функционал ПЗУ/самопрограммирование) ; регистры Xh:Xl, Yh:Yl, Zh:Zl определены в дефайне изготовителя и в системе команд ; изменение их имени хотя и возможно, но нежелательно - ; возникает путаница с интегрированной абревиатурой системы команд ; регистры имеют также отображение в пространстве ОЗУ 0х0000 - 0х001F
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 32
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения