|
__LDREX __STREX в STM32F407 |
|
|
|
Jun 4 2017, 13:18
|
Участник

Группа: Участник
Сообщений: 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) должна возвратить "не ноль", однако возвращает "ноль". Помогите, пожалуйста, разобраться, что я делаю не правильно?
|
|
|
|
10 страниц
« < 8 9 10
|
 |
Ответов
(135 - 149)
|
Jun 11 2017, 12:08
|
Частый гость
 
Группа: Участник
Сообщений: 182
Регистрация: 16-10-15
Пользователь №: 88 894

|
Цитата(Forger @ Jun 11 2017, 17:02)  Я именно так и делаю, но прерывания временно запрещаю, т. к. между проверкой и изменением указателя проходит время, в которое может влезть прерывание, которое обращается к тем же указателям. Без эти временных запретов в одном из моих старых проектов вылезала редкая и потому очень трудноуловимая ошибка ((( Я не понимаю, как читающий может переписать чужой указатель??? Ну не успели выбрать все данные, или наоборот - положить всё что нужное в буфер. Конец света от этого не наступает, успеете сделать когда будет такая возможность. Не понимаю, зачем жопу рвать на британский флаг??? По поводу неуловимых глюков. Я уже писал насчёт проблемы использования внешних глобальных переменных с атрибутом volatile. Прямое использование в функции под GCC4,8 и выше - будет давать ошибку. Например в простом выражении где А - внешняя глобальная volatile переменная. А= (А+ В +С +Е)/2 переменная А будет физически переписана 4 раза!!! Потому что она volatile и внешняя. Чтобы избавиться от подобного - необходимо объявить локальную переменную в пределах функции, и работать уже с ней, и уже готовый результат переписать в внешнюю А. По этой причине большая часть кода написанного под GCC4.2 - глючит. Когда стало широко применяться внеочередное исполнение инструкций в коде ARM процессоров (GCC4.8) - вздрогнули все аурдинщики, без исключения. Это отдельная тема, но вы должны быть в курсе.
|
|
|
|
|
Jun 11 2017, 12:19
|

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

|
Цитата(AVI-crak @ Jun 11 2017, 15:08)  Я не понимаю, как читающий может переписать чужой указатель??? Может перезаписать свой и исходя из этого изменить логику работы очереди, в мое случае - остановить передачу тогда, когда это делать рано. Сама очередь ничего не потеряла, но таймингки протокола на приемной стороне (внешнее устройство) были нарушены, что вызывало сбои в обмене. Тут уже озвучивал более подробно. Понимаю, ситуация крайне редкая, но мне она попила кровушки в свое время ((( Если нет желания вникать так глубоко, то я предлагаю закончить на этом обсуждение кольцевых буферов  В любом случае из этой темы я уже узнал все, что нужно по этим буферам. Есть некоторые новые вещи, о которых не задумывался ранее. Пригодятся, чтобы причесать свой код. Цитата Я уже писал насчёт проблемы использования внешних глобальных переменных с атрибутом volatile. Я нигде не использую глобальные переменные. Ни одной. Цитата По этой причине большая часть кода написанного под GCC4.2 - глючит. ... Это отдельная тема, но вы должны быть в курсе. Я уже давно не пользую GCC, поэтому вообще не в курсе его костылей (( А ардуино использую лишь для примитивных разовых поделок, скажем, проверить по-быстрому какой-нить новый компонент. Как макетку с мозгами. ps А вообще при чем тут gcc?
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 11 2017, 13:07
|
Частый гость
 
Группа: Участник
Сообщений: 182
Регистрация: 16-10-15
Пользователь №: 88 894

|
Цитата(Forger @ Jun 11 2017, 18:19)  Может перезаписать свой и исходя из этого изменить логику работы очереди, в мое случае - остановить передачу тогда, когда это делать рано. Сама очередь ничего не потеряла, но таймингки протокола на приемной стороне (внешнее устройство) были нарушены, что вызывало сбои в обмене. Да ёёёё. Кто-ж использует кольцевой буфер для физических устройств????? Для физики все (без исключения) применяют линейный буфер: одинарный или двойной - для одного!!! направления. Спокойно создаём сообщение, дожидаемся готовности физики, и пинаем дма. Всё, тайминги в порядке, процессорное время свободно, мозг никто не клюёт.
|
|
|
|
|
Jun 11 2017, 13:19
|

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

|
Цитата(AVI-crak @ Jun 11 2017, 16:07)  Кто-ж использует кольцевой буфер для физических устройств????? Я использую, вполне успешно ))) Особенно там, где DMA нет или он не доступен для этой физики. Но сам кольцевой буфер у меня одинаковый для всех проектов без привязки к физике, вообще ни к чему не привязан. Не пойму, почему с физикой нельзя использовать кольцевой буфер? Цитата Для физики все (без исключения) применяют линейный буфер: одинарный или двойной - для одного!!! направления. И я использую такую штуку в небольших проектах, правда, у меня это называется несколько иначе, но сути не меняет
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 11 2017, 13:59
|

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

|
Цитата(AHTOXA @ Jun 11 2017, 16:42)  Вот тут не верю. Вы только что нам тут расписывали, как вы атомарно вычитываете два указателя, вычисляете их разницу, и тут же запрещаете/разрешаете прерывания. Это невозможно выполнить с отдельным буфером. Возможно, если делать это снаружи соотв. методов, а не внутри, как у меня было раньше. Сначала запрещаются соотв. прерывания, которые могут нарушить логику работы, и уже потом оперируем данными. Но можно реализовывать критические секции и внутри методов очереди (см. ниже enterCritical / exitCritical ). Цитата Такая функциональность может быть только встроенной в буфер. Ну либо вы в прерывании напрямую модифицируете переменные структуры буфера, Все поля класса Queue - закрытые, private. Вообще, во всех классах поля закрытые, только часть методов доступна владельцу объекта. Равно как и класс имеет право обращаться лишь к некоторым методам его владельца. Поэтому нет никакого прямого доступа к полям Queue, впрочем, как и к любому другому классу. Цитата Это невозможно выполнить с отдельным буфером. Все возможно, если писать под с++ используя и шаблоны ))) У меня используется шаблон очереди, а у него впрочем как у каждого объекта есть поле владельца (owner). При создании и инициализации объекта очереди ей передается ссылка на ее владельца, уже который имеет обязательные методы enterCritical и exitCritical, доступные этому экземпляру Queue их и вызывают соотв. методы очереди. Пока что до данного момента было так ... зы. Предлагаю уходить в другую тему, иначе погонят не спрашивая...
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 12 2017, 09:12
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(Forger @ Jun 11 2017, 18:59)  Возможно, если делать это снаружи соотв. методов, а не внутри, как у меня было раньше. Сначала запрещаются соотв. прерывания, которые могут нарушить логику работы, и уже потом оперируем данными. Ага, то есть, в очереди таки ничего запрещать не надо? Ну надо же!  Цитата(Forger @ Jun 11 2017, 18:59)  Но можно реализовывать критические секции и внутри методов очереди (см. ниже enterCritical / exitCritical ). В любом случае, очередь не в курсе про прерывания от, например, UART. А полное запрещение прерываний не всегда желательно. Вы, конечно, можете сказать, что owner может предоставить методы enterCritical / exitCritical, которые как раз запрещают/разрешают прерывания от UART. Но ведь вам не всегда надо разрешать, а только когда очередь не пуста. А такую функциональность в очередь уже не встроить. Цитата(Forger @ Jun 11 2017, 18:59)  зы. Предлагаю уходить в другую тему, иначе погонят не спрашивая...  Давайте уже закругляться, новых идей нет, а по пятому кругу обсуждать одно и то же смысла особого нет.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jun 12 2017, 09:29
|

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

|
Цитата(AHTOXA @ Jun 12 2017, 12:12)  Вы, конечно, можете сказать, что owner может предоставить методы enterCritical / exitCritical, которые как раз запрещают/разрешают прерывания от UART. Именно так я и скажу  Цитата Но ведь вам не всегда надо разрешать, а только когда очередь не пуста. А такую функциональность в очередь уже не встроить. Ничего страшного в запрете каждый раз нет, главное - запрещать только от того, кто может прервать, а не от всех источников прерываний. Но ни что не мешает вынести запреты наружу и защищать лишь критичные куски кода в фоне задач и то только там, где это действительно нужно. зы Если есть еще какие вопросы, предлагаю перейти в другую тему или в личку ))
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 12 2017, 10:12
|
Частый гость
 
Группа: Участник
Сообщений: 182
Регистрация: 16-10-15
Пользователь №: 88 894

|
Цитата(Forger @ Jun 12 2017, 15:29)  Именно так я и скажу  Где именно вы умудряетесь нарушить алгоритм? 1 прочитать в ЛОКАЛЬНЫЕ переменные указатели кольцевого буфера 2 обработать данные (записать или прочитать), если таковые имеются 3 переписать ОДИН указатель по ЗАВЕРШЕНИЮ работы с данными. Прошу внимательно прочитать, и дать простой ответ под номером строки 1-2-3. При выходе из этого цикла данные записанные в буфер теряют актуальность. Не в том смысле что их можно портить, это больше похоже на лог, данные не актуальны в следующий момент времени. Например нельзя дописывать в буфер или прочитывать старое уже после выхода из полного цикла, данные теряют актуальность, и могут затереться другим процессом. Прервать алгоритм можно в любом месте, например прерыванием или переключением задач. Главное корректно его восстанавливать.
|
|
|
|
|
Jun 12 2017, 10:18
|

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

|
Цитата(AVI-crak @ Jun 12 2017, 13:12)  Где именно вы умудряетесь нарушить алгоритм? Друзья, все, что я хотел сказать по этой теме, тут уже прозвучало, повторяться не хочу. Если не согласны со моими выкладками, дело - ваше, переубеждать боле не стану, не вижу смысла. И давайте уже заканчивать эту канитель ))
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 12 2017, 11:26
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(AVI-crak @ Jun 12 2017, 15:12)  Где именно вы умудряетесь нарушить алгоритм? 1 прочитать в ЛОКАЛЬНЫЕ переменные указатели кольцевого буфера 2 обработать данные (записать или прочитать), если таковые имеются 3 переписать ОДИН указатель по ЗАВЕРШЕНИЮ работы с данными. Прошу внимательно прочитать, и дать простой ответ под номером строки 1-2-3. Я отвечу за Forger-а, а то он как-то невнятно объясняет. Он описал такой случай: изначально буфер не пуст. Мы собираемся добавить туда элемент. Между 1 и 2 произойдёт прерывание, забирающее данные из буфера, опустошит буфер, и отключит прерывания на передачу, а мы потом (после пункта 2) не включим прерывания передатчика, потому что судя по нашим локальным копиям указателей буфер был не пуст. Я лично считаю, что это не дело буфера - включать прерывания от передатчика, и такой глюк не является глюком буфера. Кроме того, в последующих сообщениях выяснилось, что и сам Forger использует реализацию буфера, которая не умеет включать прерывания передатчика. Но чего не скажешь в пылу полемики
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Jun 13 2017, 11:45
|
Частый гость
 
Группа: Участник
Сообщений: 180
Регистрация: 5-04-09
Пользователь №: 47 205

|
Цитата(jcxz @ Jun 8 2017, 23:32)  Вы это расскажите NXP с их линейкой LPC43xx. Про свои определения.  Определения читайте у ARM. [CENSORED] ничего не меняют.
Сообщение отредактировал IgorKossak - Jun 19 2017, 09:49
Причина редактирования: брань
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|