Jump to content

    

__LDREX __STREX в STM32F407

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.

Share this post


Link to post
Share on other sites
- LDREX/STREX применять только в паре, они для этого сделаны. Все остальное - от лукавого.

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

Share this post


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

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

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

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

 

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

Share this post


Link to post
Share on other sites
И правильно! Через DMA и пр. - ЗАЧЕМ???

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

 

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

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

 

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

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

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

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

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

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

Share this post


Link to post
Share on other sites

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

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

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

 

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

Share this post


Link to post
Share on other sites
Вобщем, все на откуп реализации:

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

 

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

 

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

Share this post


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

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

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

 

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

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

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

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

Share this post


Link to post
Share on other sites
Есть архитектура, есть реализация.

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

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

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

Share this post


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

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

 

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

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

 

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

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

 

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

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

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

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

Share this post


Link to post
Share on other sites

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

 

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

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

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

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

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

 

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

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

Share this post


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

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

Share this post


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

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

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

 

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

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

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

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

Share this post


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

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

 

Share this post


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

 

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

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

 

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

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

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

 

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

 

 

 

 

Share this post


Link to post
Share on other sites
хочется ведь гипотетического универсального решения

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

 

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

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

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

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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this