реклама на сайте
подробности

 
 
> __LDREX __STREX в STM32F407
_lexa_
сообщение Jun 4 2017, 13:18
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 23
Регистрация: 23-03-15
Пользователь №: 85 852



Всем доброе время суток!

IDE - IAR+плагин IAR для eclipse+eclipse.
Решил проверить, как работает синхронизация с использованием __LDREX/__STREX. Пишем следующий код
CODE
typedef struct
{
...
volatile unsigned long sync; //переменная для синхонизации доступа к данному элементу
} burst_measur;

burst_measur cur_mes;

void mpu_cfg_test()
{
//настраиваем область внутренней RAM, как разделяемую
__DMB();
SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
MPU->CTRL = 0U;

MPU->RNR = 0UL;
MPU->RBAR = 0x20000000UL;
MPU->RASR = (0x10UL << MPU_RASR_SIZE_Pos) | MPU_RASR_C_Msk | MPU_RASR_S_Msk | (0x3 << MPU_RASR_AP_Pos) | MPU_RASR_ENABLE_Msk;

MPU->CTRL = MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
__DSB();
__ISB();

//выполняем запрос эксклюзивного доступа к переменной cur_mes.sync
DWORD sync=0;
sync = __LDREX(&cur_mes.sync);
__DMB();
soft_int_ini(); //настойка программного прерывания
soft_int_on(); //вызов программного прерывания
__WFI();
}


в обработчике программного прерывания:
CODE
DWORD sync;
do
{
sync = __LDREX(&cur_mes.sync);
sync++;
sync = __STREX(sync, &cur_mes.sync);
}
while (sync);


Т.е. сначала выполняется __LDREX(&cur_mes.sync), потом происходит прерывание и выполняется __LDREX(&cur_mes.sync) + __STREX(sync, &cur_mes.sync).
По всем документациям, как я их понял, __STREX(sync, &cur_mes.sync) должна возвратить "не ноль", однако возвращает "ноль".

Помогите, пожалуйста, разобраться, что я делаю не правильно?

Go to the top of the page
 
+Quote Post
10 страниц V  « < 5 6 7 8 9 > »   
Start new topic
Ответов (90 - 104)
jcxz
сообщение Jun 9 2017, 20:27
Сообщение #91


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Forger @ Jun 9 2017, 21:39) *
Самое простое - критическими секциями.

Да... похоже Вы не понимаете.... smile3046.gif
Ниже привожу классическую реализацию кольцевого буфера.
Данная реализация позволяет:
вызывать функцию read() в читающем процессе/ядре;
вызывать функцию write() в пишущем процессе/ядре;
вызывать функции cnt() и free() в читающем и пишущем процессе/ядре.
Никаких дополнительных критических секций или запрещений прерываний или LDREX/STREX или другого шаманства - не требуется.
Данную реализацию кольцевого буфера можно использовать даже если читающий и пишущий процессы находятся в разных ядрах (процессорах).
Теперь покажите пожалуйста нам всем и объясните - где и зачем по Вашему в приведённом ниже коде нужны критические секции???
CODE
class Ring {
int volatile rpos, wpos;
u8 volatile buf[SIZE];
public:
void init() { wpos = rpos = 0; }
int read();
int write(int);
int cnt() const;
int free() const;
};

//Чтение байта данных из buf.
//return: <0 - buf пуст; >=0 - считанное значение.
int Ring::read()
{
int i, j = rpos;
if (j == wpos) return -1;
i = buf[j];
if (--j < 0) j = sizeof(buf) - 1;
rpos = j;
return i;
}

//Запись байта данных c в buf.
//return: !=0-запись успешна; ==0 - запись неуспешна (buf полон).
int Ring::write(int c)
{
int j = wpos;
u8 volatile *p = &buf[j];
if (--j < 0) j = sizeof(buf) - 1;
if (j == rpos) return 0;
*p = c;
wpos = j;
return 1;
}

//return: кол-во данных в buf.
int Ring::cnt() const
{
int i = rpos;
if ((i -= wpos) < 0) i += sizeof(buf);
return i;
}

//return: кол-во свободного места в buf.
int Ring::free() const
{
int i = wpos;
if ((i -= rpos) <= 0) i += sizeof(buf);
return i - 1;
}


PS: Я много раз не случайно подчёркивал - процесса или ядра. Так как процесс, выполняющийся на одном ядре, не может загнать процесс другого ядра в критическую секцию. Тогда следуя Вашей логике - кольцевые буфера для межъядерного обмена невозможно использовать. А их используют! laughing.gif

PSS: Приведённый код можно использовать, модифицировать и распространять совершенно свободно. Разрешаю cool.gif
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 9 2017, 20:44
Сообщение #92


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(jcxz @ Jun 9 2017, 22:37) *
Допустим пишущий процесс считал указатель чтения и, пока он его анализировал, произошло прерывание чтения, которое убавило данных из буфера.

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

Поясню.
Скажем в очереди остался всего один элемент.
Нужно туда положить еще один, он последний в отправляемом пакете.
Кладем его в голову очереди, далее должны сдвинуть указатель головы, но не успели - произошло прерывание передатчика.
В нем мы видим, что очередь непустая (сравнили два указателя), еще есть один элемент. Но всего один.
Отправляем его, сдвигаем хвост. Видим, что хвост и голова совпали - прекращаем передачу и формируем соотв. сообщение.
Возвращаемся из прерывания, сдвигаем голову вперед на один.
Ждем сообщения об окончании всей передачи, в том числе и этого последнего байта.
Успешно его дожидаемся, ведь передача была только что прекращена.
В итоге последний элемент данных не был отправлен.

В следующем пакете он будет отправлен, но он попадет в начало след. пакета.
В пакетных протоколах эта ситуация недопустима - нарушается содержимое пакетов, если, конечно, имеют значения интервалы между пакетами и между элементами данных.
Простой пример - пакетная передача по USART обычными байтами.

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


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 9 2017, 20:58
Сообщение #93


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Forger @ Jun 9 2017, 22:44) *
Понимаю, ситуация редкая и очень трудноуловимая, но она вполне возможна.

Это не редкая ситуация. Это вообще не имеет никакого отношения к работе кольцевого буфера.
Кольцевой буфер - это только кольцевой буфер, а Вы описываете случай его использования для некоей задачи.
Эта задача реализована неправильно. К работе кольца это отношения не имеет.
Так можно предположить что и в процессе передачи вашего пакета, пишущий процесс не успеет дописать достаточно данных в буфер в любом месте, а не только в последнем байте. И в любом месте будет сбой.
Это просто неправильная реализация процесса передачи, а не кольцевого буфера.
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 9 2017, 20:59
Сообщение #94


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



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


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 9 2017, 21:10
Сообщение #95


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Forger @ Jun 9 2017, 22:59) *
Кстати, при очистке очереди изменяются оба указателя (приравниваются либо друг к другу, либо к нулю).
Чистку очереди в реальном коде приходится делать, хотя бы в случае сбоев передачи по каналу связи.
Так вот эта самая чистка уж однозначно должна быть атомарной.

Опять нет rolleyes.gif
flush() в читающем процессе: Ring::flush() { rpos = wpos; } - однозначно очистка атомарна без всяких крит. секций
"Реальный код" не ограничивается только передачами по каналу связи. И далеко не везде нужен flush(). Даже скорей - редко где нужен. имха
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 9 2017, 21:15
Сообщение #96


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(jcxz @ Jun 9 2017, 23:58) *
К работе кольца это отношения не имеет.
Да неужели?
Речь тут как раз про возвожность разорвать атомарную операцию записи в буфер обработчиком, который к этому же очереди и обращается.
Пусть заполнение буфера и передача обращаются к разным указателям, но как минимум факт исчерпания очереди требует чтения обоих указателей.
Поэтому операция записи по указателю и его инкремента должна быть атомарной.
Либо не использовать прерывания.

Цитата
Так можно предположить что и в процессе передачи вашего пакета, пишущий процесс не успеет дописать достаточно данных в буфер в любом месте, а не только в последнем байте. И в любом месте будет сбой.

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



Цитата(jcxz @ Jun 10 2017, 00:10) *
flush() в читающем процессе: Ring::flush() { rpos = wpos; } - однозначно очистка атомарна без всяких крит. секций

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

Цитата
"Реальный код" не ограничивается только передачами по каналу связи. И далеко не везде нужен flush(). Даже скорей - редко где нужен. имха

Он нужен лишь при аварийных ситуациях, в штатном коде он действительно не нужен.
Я описал устройство, которое работает долго и без обслуги. Если повиснет и не сможет себя привести в норму самостоятельно, то беда будет (((


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 9 2017, 21:20
Сообщение #97


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Forger @ Jun 9 2017, 23:15) *
Пусть заполнение буфера и передача обращаются к разным указателям, но как минимум факт исчерпания очереди требует чтения обоих указателей.
Поэтому операция записи по указателю и его инкремента должна быть атомарной.
Либо не использовать прерывания.

Ещё раз: покажите в приведённом мной примере: прерывание в каком месте может разрушить его работу???
Ткните пальцем.

Цитата(Forger @ Jun 9 2017, 23:15) *
Нет, неатомарна - обычная операция чтение-модификация-запись. Может быть прервана прям посреди.
Или же прервать другое обращением к этим же полям в фоне задач.

И что? Работа кольца будет разрушена?
Да хоть 100500 обращений. На работу кольца это никак не повлияет.
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 9 2017, 21:20
Сообщение #98


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(jcxz @ Jun 10 2017, 00:17) *
Ещё раз: покажите в приведённом мной примере: прерывание в каком месте может разрушить его работу???

Вычитали один указатель (положили например в R1), произошло прерывание, изменило значение указателя.
Вернулись, присвоили другому указателю старое значение, которое положили до этого в R1.
Теперь два указателя не одинаковые, а код предполагает, что одинаковые. Как после этого поведет себя код никто не знает.


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 9 2017, 21:24
Сообщение #99


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Forger @ Jun 9 2017, 23:15) *
При чем тут не успеет дописать? В том примере все как раз и успевается и места в буфере полно.
Передача производится одновременно с заполнением буфера новыми данными. Вполне обычная ситуация.

тот пример, который Вы описали, вообще никак не говорит о правильности работы кольца. Это пример неправильного его использования.
Отвёрткой тоже можно болты закручивать, а можно её в ухо засунуть. И то, что кто-то после этого оглохнет, не означает, что отвёртка неправильная или неправильно сделана. smile3046.gif
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 9 2017, 21:27
Сообщение #100


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(jcxz @ Jun 10 2017, 00:20) *
Да хоть 100500 обращений. На работу кольца это никак не повлияет.

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

Цитата(jcxz @ Jun 10 2017, 00:24) *
тот пример, который Вы описали, вообще никак не говорит о правильности работы кольца. Это пример неправильного его использования.

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


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 9 2017, 21:29
Сообщение #101


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Forger @ Jun 9 2017, 23:20) *
Вычитали один указатель (положили например в R1), произошло прерывание, изменило значение указателя.
Вернулись, присвоили другому указателю старое значение, которое положили до этого в R1.

Ничего не понял.... wacko.gif
Какие "один" и "другой" указатель? Что за "старое" значение? Какой R1?
Я же просил - покажите на приведённом мной примере где, в каком месте прерывание (или что там ещё) нарушит его работу???
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 9 2017, 21:32
Сообщение #102


Профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 22-02-05
Пользователь №: 2 831



Цитата(jcxz @ Jun 10 2017, 00:29) *
Ничего не понял.... wacko.gif
Вот именно! Один про Фому, а второй - про Ерёму ))

Цитата
Я же просил - покажите на приведённом мной примере где, в каком месте прерывание (или что там ещё) нарушит его работу???

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


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 9 2017, 21:35
Сообщение #103


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Forger @ Jun 9 2017, 23:27) *
Я ж говорю, ни при чем тут кольцо как таковое, речь про ситуации исчерпания и переполнения буфера, которые обращаются к обоим указателям.

Может хватит наконец-то пустословия? Покажите на моём примере ГДЕ ПРОБЛЕМА???

Цитата(Forger @ Jun 9 2017, 23:27) *
Очень убедительный довод. Оказывается, что кольцо еще и использовать нужно как-то по хитрому, чтобы оно правильно работало sm.gif
Нафик тогда нужно такое кольцо, вокруг которого нужно плясать с бубном?

Прочитайте выше ещё раз про отвёртку.
Или нафик такая отвёртка, которой ухо сломать можно? biggrin.gif biggrin.gif biggrin.gif biggrin.gif

Цитата(Forger @ Jun 9 2017, 23:32) *
Например, внутри flush. Прямо посреди операции чтения-модификации-запись произойдет прерывание, которое в данный момент работает с этой же очередью.

Произойдёт прерывание, которое внутри вызовет write()? И что? Это никак не нарушит кольцо. Подумайте. rolleyes.gif
Go to the top of the page
 
+Quote Post
AVI-crak
сообщение Jun 9 2017, 22:12
Сообщение #104


Частый гость
**

Группа: Участник
Сообщений: 182
Регистрация: 16-10-15
Пользователь №: 88 894



Цитата(Forger @ Jun 9 2017, 22:27) *
Поменять шило на мыло?
По вашей логике получится, что пока этот приоритетный SVC не отработает, ни одно более важное аппаратное прерывание не пройдет.
SVC с таким высоким приоритетом, вызываемые из других менее приоритетных прерываний по сути временно задирает их собственный приоритет, который был "ниже плинтуса", отбирая "право голоса" у более приоритетных прерываний.
На лицо - инверсия приоритетов. С чем боролись на то и напоролись. Ни чем не лучше глобальной критической секции (запрет/разрешение всех прерываний).

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

Цель - сохранить стек без использования мази от геморроя.
Запреты прерываний - вот настоящий геморрой.

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

Складывается ощущение, что не каждый понимает о чём тут разговор. Но читать приятно.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 9 2017, 22:28
Сообщение #105


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(AVI-crak @ Jun 10 2017, 00:12) *
Насчёт кольцевого буфера (знатный срачь):
...
Складывается ощущение, что не каждый понимает о чём тут разговор. Но читать приятно.

Может быть Вы укажете, где именно проблема в приведённом мной примере реализации кольцевого буфера?
А то Forger видимо знает, но держит эту тайну при себе biggrin.gif
Go to the top of the page
 
+Quote Post

10 страниц V  « < 5 6 7 8 9 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 22:14
Рейтинг@Mail.ru


Страница сгенерированна за 0.01518 секунд с 7
ELECTRONIX ©2004-2016