Доброго времени суток. Подскажите как организовать атомарные функции в кейл контроллер aduc7024 ядро ARM7. Тему штудировал но такие вещи как atomic block не нашел? просто запретить прерывание тоже не совсем то.
1. Реализуй какое-нибудь средство синхронизации, например, семафоры. Я думаю в интернете найдется много статей как это сделать.
2. Если запрещать все прерывания не охота, то запрещай только то, которое использует эту функцию.
Если функция вызывается только из прерываний, то не имеет смысла что-либо с ней делать, потому что контроллер прерываний не поддерживает вложенные прерывания, то есть прерывание не может прервать другое прерывание. Это конечно можно обойти, но надо реализовывать ручками функцию-обертку для прерываний.
Так то у него не Cortex, да и судя по описанию они никак не помогут в реализации атомарной операции.
DMB Data Memory Barrier acts as a memory barrier. It ensures that all explicit memory accesses that appear in program order before the DMB instruction are observed before any explicit memory accesses that appear in program order after the DMB instruction. It does not affect the ordering of any other instructions executing on the processor.
Как я понял она предотвращает возможное внеочередное исполнение команд доступа к памяти. То что находится после нее не может быть выполнено раньше, чем то, что находится до нее и наоборот.
DSB Data Synchronization Barrier acts as a special kind of memory barrier. No instruction in program order after this instruction executes until this instruction completes. This instruction completes when: All explicit memory accesses before this instruction complete. All Cache, Branch predictor and TLB maintenance operations before this instruction complete.
Как я понял это некий способ удостоверится, что перечисленные операции (explicit memory accesses, Cache, Branch predictor and TLB maintenance operations) полностью завершены к моменту "выхода" из этой инструкции.
Однако, начиная с ARMv6 есть инструкции которые действительно могут помочь (только помочь) в реализации средства синхронизации: LDREX и STREX. Но ARM7 реализует ARMv4 и там этого нету. Так что в любом случае придется делать что-то самому на Си или на Си+Ассемблер.
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Однако, начиная с ARMv6 есть инструкции которые действительно могут помочь (только помочь) в реализации средства синхронизации: LDREX и STREX. Но ARM7 реализует ARMv4 и там этого нету.
Да, в сортах процессоров не разбираюсь, казалось что Thumb давно уже везде есть . LDREX и STREX хорошие инструкции. Но лично мне достаточно и простого чтения/записи в память. Достаточно того, что 4-x байтовые слова пишутся и читаются атомарно.
Так что ждем от автора темы подробного описания зачем это надо. Таки у него не многопроцессорная система, так что элементарно должно быть все.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Код внутри SetFlagsis в общем случае не решает задачи. Потому как сразу после проверки внутри if может вызваться прерывание, и очистить эту переменную.
Таки тебе надо описать задачу. Подозреваю, что там логическая проблема с управлением этим флагом.
Если проверка и установка битов в фоне происходит не слишком часто, то не вижу ничего плохого в запрещении прерывании, которое будет длиться (имеется в виду запрещение) всего несколько тактов. На сколько часто они устанавливаются в прерываниях - не важно, потому что как я уже говорил в ARM7 прерывания не могут прерывать друг-друга и от использования __disable_irq()/____enable_irq() им ни тепло ни холодно.
А вообще я нашел документ от ARM, где вроде бы описано как реализовать синхронизацию (семафор или мьютекс), используя специальные инструкции. То что тебе надо находится в конце (appendix), там где про старые архитектуры до версии ARMv6.
Спасибо за ссылку документ сохранил. У меня проблем в коде нет, в данный момент разрабатываю программу от стабильности которой зависит здоровье людей (проект называть не имею права...). В связи с чем хочу избежать глюков связанных "с фазой луны ))" я понимаю, что разрыв модификации переменной может привести к "красивым" глюкам. Система критична ко времени (реалтайм система). От выше перечисленной переменой в принципе стабильность мало зависит но все таки... в программе использую протопотоки по этому процессы друг на друга не накладываются. А спрашиваю для того, что-бы избежать глюков с атомарностью, при этом данные модули не должны задерживать прерывания.
По поводу протопотоков, может откажусь от них немного тормознутая вещь... над проектом только начал работу до конца не решил всю структуру программы, ОС однозначно использовать не буду. Смотрю на написание кооперативной многозадачности, но тема для меня новая поэтому пока остановился на протопотоках так как с их помощью получается не сложная диспетчеризация, ну или по крайней мере мне так показалось.
В процессорах до версии ARMv6 единственные инструкции для атомарных операций -- это SWP и SWPB. Они считывают из памяти одно значение и заменяют другим, при этом в промежутке между чтением и записью никто вклиниться не может. Но, если система однопроцессорная, то в них нужды нет: достаточно запрещать прерывания на время чтения-сравнения-модификации тех или иных переменных. Но в любом случае это низкоуровневые механизмы, а задачу надо сначала решить на высоком уровне (т.е. понять, что же конкретно нужно).
Что делать ? пришел к выводу что необходимо запрещать прерывания на время модификации очереди задач, и флага состояния, эти процедуры модифицируется как в прерывании так и в основной ветке, но как написал выше кейловские функции шлепают мне программу. Проверял без них работает нормально.
В процессорах до версии ARMv6 единственные инструкции для атомарных операций -- это SWP и SWPB. Они считывают из памяти одно значение и заменяют другим, при этом в промежутке между чтением и записью никто вклиниться не может. Но, если система однопроцессорная, то в них нужды нет: достаточно запрещать прерывания на время чтения-сравнения-модификации тех или иных переменных. Но в любом случае это низкоуровневые механизмы, а задачу надо сначала решить на высоком уровне (т.е. понять, что же конкретно нужно).
По поводу SWP и SWPB ниже пример кода, чтобы в данном случае сделать атомарность как я понял функцию необходимо написать на АСМ и вклинить между SWP и SWPB? Т.Е. Си функцию туда уже не вклинишь.
Код:
SWP R0,R1,[R2] ; Загрузить в R0 слово по адресу в R2, и сохранить R1 в R2. SWPB R2,R3,[R4] ; Загрузить в R2 байт по адресу в R4, ; и сохранить младший байт R3 в R4. SWPEQ R0,R0,[R1] ; По условию обменять слово, определенное по адресу в R1 ; и содержимым в регистре R0.
1. Странно, что они у тебя рушат программу, я их использовал вполне успешно. Что именно работает не так?
2. Функции __enable/__disable запрещают прерывания модифицируя регистр состояния ядра. Если не получается использовать их, то как я уже говорил, можешь запрещать прерывания в контроллере прерываний. Во-первых, можно будет запретить только те прерывания, которые осуществляют доступ к защищаемым данным, оставив остальные прерывания разрешенными, что может повысить "отзывчивость" системы. Во-вторых, при запрещении через контроллер прерываний ломаться просто нечему, все должно работать как надо.
3. Насчет примитивов синхронизации, типа SWP, LDREX и других. Они всего-лишь примитивы, основа для реализации полноценного и удобного средства синхронизации на Си/Си++, которое можно использовать как угодно, оборачивать любые участки кода и т.п. А иначе, действительно придется реализовывать функцию на ассемблере, или использовать какие-нибудь ассемблерные вставки в Си, что по моему мнению является костылем.
Я за запрещение прерываний через VIC. Это не потребует никаких лишних затрат и должно хорошо работать.
Если делать спин-блокировку (т.е. поток тупо крутится в цикле захвата блокировки до тех пор, пока не захватит), то последовательность действий примерно такова:
1. Изначальное состояние спин-блокировки (байта или слова в памяти) -- нуль. 2. Когда поток хочет захватить блокировку, он делает SWP или SWPB, запихивая в блокировку любое ненулевое значение. После этого он проверяет, что было из блокировки считано. Если был считан не нуль (т.е. если блокировка уже была захвачена другим потоком), он повторяет п. 2 -- и так до тех пор, пока не будет считан нуль. 3. Блокировка захвачена. Поток выполняет свои чёрные дела, для которых ему требовалась блокировка. 4. Закончив дела, поток записывает в блокировку нуль (не через SWP, а обычным STR -- здесь доступ к памяти однократный, а не дважды подряд, поэтому нужды в SWP нет).
У этой схемы есть тот недостаток, что, если потоки не переключаются каким-то внешним для них образом, программа "зависнет" при неудачной попытке захвата спин-блокировки. Т.е. необходимо обеспечить, чтобы, обнаружив, что блокировка уже занята, поток передавал управление другому потоку (который и захватил эту блокировку) и лишь потом опять повторял попытку захвата. Ну а как это сделать, зависит целиком от программиста и используемой им ОС.
А вот насчёт приведённого Вами фрагмента кода я, честно говоря, ничего не понял. Зачем там три команды SWP и как вообще Вы собираетесь вести обработку?
1. Странно, что они у тебя рушат программу, я их использовал вполне успешно. Что именно работает не так?
2. Функции __enable/__disable запрещают прерывания модифицируя регистр состояния ядра. Если не получается использовать их, то как я уже говорил, можешь запрещать прерывания в контроллере прерываний. Во-первых, можно будет запретить только те прерывания, которые осуществляют доступ к защищаемым данным, оставив остальные прерывания разрешенными, что может повысить "отзывчивость" системы. Во-вторых, при запрещении через контроллер прерываний ломаться просто нечему, все должно работать как надо.
3. Насчет примитивов синхронизации, типа SWP, LDREX и других. Они всего-лишь примитивы, основа для реализации полноценного и удобного средства синхронизации на Си/Си++, которое можно использовать как угодно, оборачивать любые участки кода и т.п. А иначе, действительно придется реализовывать функцию на ассемблере, или использовать какие-нибудь ассемблерные вставки в Си, что по моему мнению является костылем.
Я за запрещение прерываний через VIC. Это не потребует никаких лишних затрат и должно хорошо работать.
Точно я за VIC не подумал, спасибо за подсказку.
По поводу потоков там все макросы для безопасной работы присутствуют, например, есть мьютексы, PT_END, PT_EXIT и пр. если интересно как строить OC на протопотоках, можно прочитать о них, например, тут [url]sics.se/~adam/pt/[/url]
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 36
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения