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

AHTOXA, спасибо, ознакомился.

Но, опять противоречивые результаты:

AVI-crak говорит, что флаг сбрасывает любая запись по адресу, хоть DMA.

ArtDenis в своих тестах показывает, что даже явная запись не сбрасывает.

AlexandrY утверждает, что у него явная запись сбрасывает флаг, а неявная (PUSH) - не меняет состояние.

 

Походу, собака порылась в

A3.4.5 Load-Exclusive and Store-Exclusive usage restrictions

The Load-Exclusive and Store-Exclusive instructions are designed to work together, as a pair, for example a

LDREX/STREX pair or a LDREXB/STREXB pair. As mentioned in Context switch support, ARM recommends that the

Store-Exclusive instruction always follows within a few instructions of its associated Load-Exclusive instructions.

In order to support different implementations of these functions, software must follow the notes and restrictions

given here.

...

В частности, по поводу простой записи:

• An explicit store to memory can cause the clearing of exclusive monitors associated with other processors,

therefore, performing a store between the LDREX and the STREX can result in a livelock situation. As a result,

code must avoid placing an explicit store between an LDREX and an STREX in a single code sequence.

• LDREX and STREX operations must be performed only on memory with the Normal memory attribute.

 

То есть:

- LDREX/STREX применять только в паре, они для этого сделаны. Все остальное - от лукавого. Может сработать, а может и нет, зависит от конкретной реализации ядра

- LDREX/STREX применять только на Normal памяти:

A3.5.1 Memory types

For each memory region, the most significant memory attribute specifies the memory type. There are three mutually

exclusive memory types:

• Normal.

• Device.

• Strongly-ordered.

- вроде как сброс локального монитора текущего ядра может происходить при ЛЮБОЙ записи (хоть DMA), при ЯВНОЙ записи могут сбросится только мониторы других ядер. Но по факту может быть что угодно в зависимости от конкретной реализации. Извращения проверять обязательно!

A3.4.1 Exclusive access instructions and Non-shareable memory regions

When a processor writes using any instruction other than a Store-Exclusive:

• If the write is to a physical address that is covered by its local monitor it is IMPLEMENTATION DEFINED

whether the write affects the state of the local monitor.

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

A3.4.4 Context switch support

In ARMv7-M, the local monitor is changed to Open Access automatically as part of an exception entry or exit sequence.

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


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

- LDREX/STREX применять только в паре, они для этого сделаны. Все остальное - от лукавого.

И правильно! Через DMA и пр. - ЗАЧЕМ???

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


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

- LDREX/STREX применять только в паре, они для этого сделаны. Все остальное - от лукавого. Может сработать, а может и нет, зависит от конкретной реализации ядра

Именно. Различия в результатах тестов вызваны, скорее всего, различиями в реализации. (Ну или кто-то накосячил в тестах:))

Способ использования от этого не меняется - только в паре.

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

 

ЗЫ. Хотя насчёт DMA - я лично не верю. В этом случае при непрерывно идущих быстрых транзакциях DMA можно наглухо зависнуть в LDREX/STREX.

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


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

И правильно! Через DMA и пр. - ЗАЧЕМ???

Импульсивный Вы наш, по делу бы что сказали!

 

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

Добавил, куда можно было. Весь этот раздел A3.4 - сплошные выводы. Читать и читать.

 

ЗЫ. Хотя насчёт DMA - я лично не верю. В этом случае при непрерывно идущих быстрых транзакциях DMA можно наглухо зависнуть в LDREX/STREX.

Мне тоже идея с DMA не очень нравится.

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

Вобщем, все на откуп реализации:

post-10882-1496922773_thumb.pngpost-10882-1496922687_thumb.png

Опыты, только опыты... Ни в одной докуметации на MCU не видел таких тонкостей.

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


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

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

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

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

 

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

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


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

Вобщем, все на откуп реализации:

Хорошие картинки, теперь понятны отличия в реализации. По идее, получается, могут существовать реализации, где DMA сбрасывает монитор. Надо будет учесть.

 

Опыты, только опыты... Ни в одной докуметации на MCU не видел таких тонкостей.

 

Думаю, это плата за универсальность ядра. АРМу пришлось при проектировании закладывать разные варианты реализации.

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


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

Именно. Различия в результатах тестов вызваны, скорее всего, различиями в реализации. (Ну или кто-то накосячил в тестах:))

Способ использования от этого не меняется - только в паре.

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

 

ЗЫ. Хотя насчёт DMA - я лично не верю. В этом случае при непрерывно идущих быстрых транзакциях DMA можно наглухо зависнуть в LDREX/STREX.

Есть архитектура, есть реализация.

На Cortex-M, которые по определению одноядерные, монитор как таковой отсутствует. Есть просто один-единственный триггер. LDREX его взводит, STREX проверяет что установлен, выполняет запись и сбрасывает. Любое исключение сбрасывает бит. Принудительно можно сбросить через CLREX.

На на навороченных многоядерных камнях с MMU, многоуровневыми кэшами, множеством bus-master устройств реализация может быть совсем другой.

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


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

Есть архитектура, есть реализация.

На Cortex-M, которые по определению одноядерные, монитор как таковой отсутствует. Есть просто один-единственный триггер. LDREX его взводит, STREX проверяет что установлен, выполняет запись и сбрасывает. Любое исключение сбрасывает бит. Принудительно можно сбросить через CLREX.

Не вижу в вашем высказывании противоречия с моим. (Или вы не возражали, а дополняли?)

И на Cortex-M есть нюансы. Где-то обычная запись сбрасывает монитор, а где-то -- нет. Где-то DMA сбрасывает монитор, а где-то -- нет.

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


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

Неявная запись (PUSH) - является отложенным событием (как и любая запись кучи регистров), код выполняется параллельно, сбросить физику с подтверждением не получится, но можно немного подождать

Сколько? Сколько вешать в граммах?

 

в пустом цикле или сбросить конвейер.

Это что такое? И как оно поможет?

 

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

DMB/DSB/и прочие B - спасут отца русской демократии :laughing:

 

На Cortex-M, которые по определению одноядерные

Вы это расскажите NXP с их линейкой LPC43xx. Про свои определения. B)

Или Ваш мир Cortex-M ограничен STM32?

Курица - не птица, Cortex-M - не STM! Рифма одна-ко. Надо в подпись внести © :biggrin:

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


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

Коли SVC синхронное и его не получиться использовать нормально в прерываниях (для lockfree решений), то может быть для этой цели подойдет pendSV?

 

А, чтобы разделить переключатель контекста rtos и юзерские вызовы этого самого pendSV, скажем, в R0 кладем адрес функции, а в остальные регистры ее параметры, а уже внутри pendSV все это разбираем.

Приоритет pendSV самый низкий (ниже лишь systick).

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

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

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

 

Или тут есть какие-то подводные камни?

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

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


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

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

PendSV не "вызывают", а лишь возбуждают запрос на него. В том числе и в ISR-ах, где вход в PendSV будет отложен до завершения всех других ISR, а из фонового процесса - вход в PendSV будет сразу, подобно синхронному SVC.

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


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

PendSV не "вызывают" ...
Да, это-то понятно, это все - придирки к словам, а речь о другом:

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

Понятно, что pendSV не для этого был задуман, но тем не менее ))

 

Размышляя вслух дальше - выполняемый в данный момент pendSV может прервать другое более приоритетное прерывание и опять накидать в стек новых данных перед взводом pendSV,

Или использовать внутри pendSV вызов соотв. SVC, который имеет приоритет выше pendSV...

Заумно как-то выходит. Но возможно ли осуществить что-то подобное?

Цель - избежать критических секций с запретом прерываний и "капризного" LDREX/STREX.

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


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

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

Очередь данных в стеке не формируется - формируйте ее отдельно, а потом обрабатывайте в PendSV. Но для данной задачи это неэффективно и не имеет смысла - есть LDREX/STREX, если его не хватает, то есть запрет части или всех прерываний.

 

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


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

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

 

Но для данной задачи это неэффективно и не имеет смысла - есть LDREX/STREX, если его не хватает, то есть запрет части или всех прерываний.

Согласен, но хочется ведь гипотетического универсального решения, вот и спрашиваю )))

 

Короче, задача довольно тривиальная:

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

Нужно защищать указатели (голова/хвост) очереди от прерывания.

 

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

 

 

 

 

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


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

хочется ведь гипотетического универсального решения

Если пишите под GCC, то можно посмотреть на atomic built-in функции https://gcc.gnu.org/onlinedocs/gcc-4.4.3/gc...c-Builtins.html .

 

Короче, задача довольно тривиальная:

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

Нужно защищать указатели (голова/хвост) очереди от прерывания.

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

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


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

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

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

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

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

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

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

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

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

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