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

 
 
> __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
 
Start new topic
Ответов
jcxz
сообщение Jun 4 2017, 17:10
Сообщение #2


Гуру
******

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



Цитата(_lexa_ @ Jun 4 2017, 15:18) *
что я делаю не правильно?

Ожидаете "не ноль".
STREX всё верно возвращает.
Go to the top of the page
 
+Quote Post
_lexa_
сообщение Jun 4 2017, 18:39
Сообщение #3


Участник
*

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



Цитата(jcxz @ Jun 4 2017, 17:10) *
STREX всё верно возвращает.

если не верно задал вопрос -
от __LDREX() + __STREX() ожидаю следующее:
если выполнено__LDREX(&cur_mes.sync)
тогда в случае выполнения в другой части кода "__LDREX(&cur_mes.sync) + __STREX(sync, &cur_mes.sync)" __STREX вернет "не ноль".
однако возвращается ноль.

Где-то ошибся! Не понятно только где. Поясните вкратце, куда смотреть.
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Jun 4 2017, 19:34
Сообщение #4


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(_lexa_ @ Jun 4 2017, 19:39) *
Где-то ошибся! Не понятно только где. Поясните вкратце, куда смотреть.

Каждый раз вспоминаю и снова забываю эти проклятые LDREX/STREX, но суть в том, что если между LDREX и последующим STREX "что-то пошло не так, Карл", а именно - возникло некоторое событие, прерывание, которое СТАВИТ ПОД УГРОЗУ целостность переменной-флага, то STREX вернет типа "ай-ай". То есть, даже если саму переменную-флаг никто и трогать не собирался где-то в недрах прерываний, но прерывание нарушило непрерывное исполнение между LDREX и STREX, то ресурс считается занятым. Поэтому у меня глубокое сомнение, можно ли строить код, как у ТС, - захватывать ресурс в основном коде и выяснять отношения в прерывании: в прерывании по определению ресурс будет занят.
Если хотите организовать всякие мъютексы и прочие разделяемые флаги на системе bare bone с наличествующими прерываниями, гляньте на команду SVC. Могу даже код кинуть, если есть интерес.
Go to the top of the page
 
+Quote Post
_lexa_
сообщение Jun 4 2017, 20:14
Сообщение #5


Участник
*

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



Цитата(KnightIgor @ Jun 4 2017, 19:34) *
... Могу даже код кинуть, если есть интерес.


Интерес есть. Кидайте.
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Jun 4 2017, 21:14
Сообщение #6


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



Цитата(_lexa_ @ Jun 4 2017, 21:14) *
Интерес есть. Кидайте.

Обработчик прерывания SVC выглядит у меня следующим образом. Много подсмотрено по ссылкам, указанным в комментариях.
Код
// ---------------------------------------------------------------------------
//
//    SVC_Handler used for "atomic" operations based on the the fact, that
//  SVC handler cannot be interrupted by higher placed interrupts.
//
//  Upon call to SVC vector the stack holds saved register:
//            xPSR          0x1C (7)
//            PC            0x18 (6)
//            R14(LR)       0x14 (5)
//            R12           0x10 (4)
//            R3            0x0C (3)
//            R2            0x08 (2)
//            R1            0x04 (1)
//     [SP]-> R0            0x00 (0)
//
//  The registers will be restored upon leaving the handler. The handler
//  to return a result, a value in the stack must be modified.
//
//  Via stacked R0..R3 the parameters can be passed through to the
//  handler. For this purpose the definition of the user SVC call can
//  be done as (the type 'int' is for example):
//
//      __svc(n) myfunc(int [,int, int, int]);
//
//  See Chapter 6.19, Figure 6.5 in:
//  http://infocenter.arm.com/help/topic/com.arm.doc.dui0471c/  \
//         DUI0471C_developing_for_arm_processors.pdf
//
//                  and    
//      
//    http://www.mikrocontroller.net/topic/295183
//    http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0471j/pge1358787038365.html
//    http://sites.fas.harvard.edu/~libe251/spring2014/CauseOfDefaultISR.txt
//
//  To PRESERVE8 for stack 8 bytes alignment see
//    http://infocenter.arm.com/help/topic/com.arm.doc.faqs/ka4127.html
//
__asm
void SVC_Handler(void) {
    
    PRESERVE8  
    EXPORT  SVC_Handler

  ; get the pointer to the saved R0-R3 to pass it
  ; to SVC_Dispatcher() as the second parameter
  ; (via R1):
    
#ifdef  SVC_OS_MODE
    
    TST     LR, #4            ; kernel mode?  
    ITE     EQ
    MRSEQ   R1, MSP        ; kernel stack
    MRSNE   R1, PSP        ; user stack    

  ; get SVC n instruction code field and
  ; pass it to SVC_Dispatcher() as the first
  ; parameter (via R0):

    LDR     R0, [R1, #6*4]    ; PC
#if defined(__CORE_CM0_H_GENERIC) || defined(__CORE_CM0PLUS_H_GENERIC)
    SUBS    R0, R0,  #2
    LDRB    R0, [R0, #0]      ; SVC OPCODE low byte
#else
    LDRB    R0, [R0, #-2]     ; SVC OPCODE low byte
#endif    

    PUSH    {LR, R1}            
    EXTERN  SVC_Dispatcher
    BL      SVC_Dispatcher    ; return value in R0
    POP     {R1}    

  ; return the result in R0 via stacked R0:

    STR     R0, [R1]        
    
#else                          
    MOV     R1, SP            ; kernel=user stack (no OS)

  ; get SVC n instruction code field and
  ; pass it to SVC_Dispatcher() as the first
  ; parameter (via R0):

    LDR     R0, [R1, #6*4]    ; PC
#if defined(__CORE_CM0_H_GENERIC) || defined(__CORE_CM0PLUS_H_GENERIC)
    SUBS    R0, R0,  #2
    LDRB    R0, [R0, #0]      ; SVC OPCODE low byte M0/M0+
#else
    LDRB    R0, [R0, #-2]     ; SVC OPCODE low byte M3 and higher
#endif    

    PUSH    {LR}              ; preserve return address
    EXTERN  SVC_Dispatcher
    BL      SVC_Dispatcher    ; return value in R0

  ; return the result in R0 via stacked R0:

    STR     R0, [SP, #4]      ; #4 to skip LR in the stack    
#endif
    
    POP    {PC}            ; exit by LR
}    
//------------------------------------------------------------------------------

Если исключить условные трансляции, которые разбирают варианты под OS, а также оставить универсальный вариант, работающий и на -M0 (не поддерживающих отрицательные смещения), то обработчик упростится для исполнения и понимания:
Код
__asm
void SVC_Handler(void) {
    
    PRESERVE8  
    EXPORT  SVC_Handler

  ; get the pointer to the saved R0-R3 to pass it
  ; to SVC_Dispatcher() as the second parameter
  ; (via R1):
    
    MOV     R1, SP            ; kernel=user stack (no OS)

  ; get SVC n instruction code field and
  ; pass it to SVC_Dispatcher() as the first
  ; parameter (via R0):

    LDR     R0, [R1, #6*4]    ; PC
    SUBS    R0, R0,  #2
    LDRB    R0, [R0, #0]      ; SVC OPCODE low byte M0/M0+

    PUSH    {LR}              ; preserve return address
    EXTERN  SVC_Dispatcher
    BL      SVC_Dispatcher    ; return value in R0

  ; return the result in R0 via stacked R0:

    STR     R0, [SP, #4]      ; #4 to skip LR in the stack    
    
    POP    {PC}            ; exit by LR
}    
//------------------------------------------------------------------------------

Как видно, все готовилось для вызова C-шной процедуры-обработчика ниже. Я выбросил многие мои специфические ветви, оставив те, что иллюстрируют идею:
Код
uint32_t SVC_Dispatcher(int svc, SVC_Param_TypeDef *ptr)
{
    uint32_t res = UINT32_MAX;
    switch (svc) {
        case _SVC_ATOMIC_FLAG8:     // atomic clear of an U8 flag
            res = *(uint8_t *)ptr->R0;      // return the last state
                  *(uint8_t *)ptr->R0 = 0;  // clear it
        break;
        case _SVC_ATOMIC_FLAG16:     // atomic clear of an U16 flag
            res = *(uint16_t *)ptr->R0;      // return the last state
                  *(uint16_t *)ptr->R0 = 0;  // clear it
        break;
        case _SVC_ATOMIC_ADD32:     // atomic add 32
            res =
            *(uint32_t *)ptr->R0 += (int32_t)ptr->R1;      
        break;
        case _SVC_ATOMIC_DEC8:
            res = *(uint8_t *)ptr->R0;
            if (res)
            {
                *(uint8_t *)ptr->R0 = --res;
            }
        break;
        case _SVC_MUTEX8:     // mutex in an U8 variable
            res = !(*(uint8_t *)ptr->R0);   // current mutex state
            *(uint8_t *)ptr->R0 = ptr->R1;  // set the value
        break;      
    }
    return res;
}

К этому пристегивается заголовок (существенный фрагмент):
Код
typedef struct svc_params_s {

    uint32_t R0, R1, R2, R3;
    
} SVC_Param_TypeDef;    

#define _SVC_GETSYSCLOCKVALUE   4
#define _SVC_ATOMIC_FLAG8       8
#define _SVC_ATOMIC_FLAG16      9
#define _SVC_ATOMIC_FLAG32      10
#define _SVC_ATOMIC_ADD8        11
#define _SVC_ATOMIC_ADD16       12
#define _SVC_ATOMIC_ADD32       13
#define _SVC_ATOMIC_DEC8        14
#define _SVC_MUTEX8             16
#define _SVC_ATOMIC_SET8        21
#define _SVC_ATOMIC_SET16       22
#define _SVC_ATOMIC_SET32       23
#define _SVC_CALL_ME_PAR        25

//------------------------------------------------------------------------------
//
//  Clears an U8 flag pointed by 'pflag' but returns its latest value.
//
uint8_t __svc(_SVC_ATOMIC_FLAG8) Atomic_Flag8(uint8_t *pflag);

//------------------------------------------------------------------------------
//
//  Adds an I32 value to the value pointed by 'pvalue' and returns the result
//
uint32_t __svc(_SVC_ATOMIC_ADD32) Atomic_Add32(uint32_t *pvalue, int32_t val);

//------------------------------------------------------------------------------
//
//  Decrements a non zero value pointed by 'pvalue' and returns the result
//
uint8_t __svc(_SVC_ATOMIC_DEC8) Atomic_Dec8(uint8_t *pvalue);

//------------------------------------------------------------------------------
//
//  Sets the mutex ('setit'=true) pointed by 'pflag' and returns true if success.
//  Otherwise the mutex has been busy.
//
//  Clears ('setit'=false) the mutex unconditionally. It's up to the user to take
//  care, if the mutex is allowed to be cleared. The return result to be ignored.
//
//  NOTE: THE MUTEX VALUE AND THE SETIT PARAMETER ARE EXPECTED TO BE ONLY 0 OR 1.
//        NO OTHER VALUES ARE ALLOWED, SHOULD FOR INSTANCE THE MUTEX VARIABLE BE
//        CHANGED ELSEWHERE.
//
int __svc(_SVC_MUTEX8) Mutex8(uint8_t *pflag, uint8_t setit);

//------------------------------------------------------------------------------

extern uint32_t SVC_Dispatcher(int svc, SVC_Param_TypeDef *ptr);

Теперь о вызове на примере флага:
Код
uint8_t sb = Atomic_Flag8(&flag); // atomic reset
if (sb) {
// ...
}

Там для некой переменной uint8_t flag, которая устанавливается в прерывании, функция возвращает мне последнее состояние флага и сбрасывает его. Благодаря непрерываемости SVC операция по сбросу флага является атомарной.

Сообщение отредактировал KnightIgor - Jun 4 2017, 21:14
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 5 2017, 05:38
Сообщение #7


фанат дивана
******

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



Цитата(KnightIgor @ Jun 5 2017, 02:14) *
Благодаря непрерываемости SVC операция по сбросу флага является атомарной.

А в чём выгода такого метода по сравнению с простым запретом/разрешением прерываний? Я думаю, что по скорости это даже медленнее (тратится время на сохранение и восстановление контекста).
Прелесть же LDREX/STREX как раз в том, что они не блокируют прерывания.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 5 2017, 08:17
Сообщение #8


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

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



Цитата(AHTOXA @ Jun 5 2017, 08:38) *
А в чём выгода такого метода по сравнению с простым запретом/разрешением прерываний?

Полагаю, что выгода в полным отсутствием этих самых запретов/разрешений.
Дабы иметь возможность гарантировать стабильную скорость реакции на критичные высокоприоритетные прерывания.
Причем, в независимости используется ось или нет.
Сам поглядываю на подобные решения, но таких у меня проектов очень мало, поэтому пока вполне хватает "классического" запрет/разрешение прерываний.
Хожу как "кот вокруг сметаны" sm.gif

Цитата
Я думаю, что по скорости это даже медленнее (тратится время на сохранение и восстановление контекста).

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


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


Гуру
******

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



Цитата(Forger @ Jun 5 2017, 10:17) *
Полагаю, что выгода в полным отсутствием этих самых запретов/разрешений.
Дабы иметь возможность гарантировать стабильную скорость реакции на критичные высокоприоритетные прерывания.

Так обработчик SVC задержит эти самые "высокоприоритетные прерывания" на ещё в разы большее время!

Цитата(Forger @ Jun 5 2017, 10:24) *
Почему непрерывный? Любое более приоритетное прерывание может его прервать в любой момент, иначе от этого SVC почти нет никакого проку .
Лишь нужно правильно настроить NVIC.

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

Цитата(Forger @ Jun 5 2017, 10:24) *
Безусловно, оверхед заметно растет, но цена этому - гарантия реакции на действительно важные события.
Под SVC вообще идеально ложатся все сервисы RTOS, судя по всему прям для них SVC и задумывалось.
Только вот мне не попадались готовые оси, где это используется ...

SVC задумывалось совсем не для этого. Для этого задумывались LDREX/STREX. Именно поэтому и нет.
Если у Вас другой обработчик может прерывать SVC, то никакой эксклюзивности уже нет. По определению.

Цитата(Forger @ Jun 5 2017, 10:24) *
Причем, это более "мощное" прерывание может вызвать это же самое SVC, а когда выйдет, продолжится обработка прерванного SVC

ну-ну... учите матчасть biggrin.gif
Если это "мощное" прерывание попытается так сделать, то получит HardFault, а не SVC.
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 5 2017, 09:11
Сообщение #10


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

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



Цитата(jcxz @ Jun 5 2017, 11:49) *
Так обработчик SVC задержит эти самые "высокоприоритетные прерывания" на ещё в разы большее время!
Потому что для работоспособности этого способа, обработчик SVC должен быть самым высокоприоритетным.

Как раз наоборот - приоритет SVC должен быть самым низким ! (ну кроме разве что PendSV).

Цитата
SVC задумывалось совсем не для этого. Для этого задумывались LDREX/STREX. Именно поэтому и нет.
Если у Вас другой обработчик может прерывать SVC, то никакой эксклюзивности уже нет. По определению.

Не путайте вызов SVC с вызовом обычной функции!

Цитата
Если это "мощное" прерывание попытается так сделать, то получит HardFault, а не SVC.

Да неужели? И по какой причине?


Цитата(AHTOXA @ Jun 5 2017, 11:54) *
Видите, "благодаря непрерываемости SVC". Это значит, что у svc в его случае самый высокий приоритет.

Вовсе нет, непрерываемость реализуется благодаря тому, что один вызов SVC не может прервать другой на уровне ЯДРА.
Другими словами все возникшие вызовы SVC становятся в очередь.

Цитата
А значит, вход в обработчик SVC блокирует остальные прерывания. Вот я и поинтересовался:

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





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


Гуру
******

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



Цитата(Forger @ Jun 5 2017, 11:11) *
Как раз наоборот - приоритет SVC должен быть самым низким ! (ну кроме разве что PendSV).
Да неужели? И по какой причине?

Если бы Вы открыли мануал на ядро, то узнали бы, что SVC является синхронным исключением. Т.е. - должно обработаться сразу же.
А если это не возможно (например - запрещены исключения или, как Вы советуете, оно вызвано внутри более приоритетного ISR), то будет активирован механизм эскалации до Hard Fault.

Цитата(Forger @ Jun 5 2017, 11:11) *
Не путайте вызов SVC с вызовом обычной функции!

Я то как раз не путаю, потому что у меня много где SVC используется. А вот Вам следовало бы хотя-бы ознакомиться с предметом, прежде чем советовать что-то.
И вызов SVC - как раз очень похож на вызов обычной функции. Для вызывающего процесса. Только на другом уровне привилегий.
Именно это и есть его главное предназначение - вызов функций с привилегиями системного уровня из прикладного уровня.

Цитата(Forger @ Jun 5 2017, 11:11) *
Другими словами все возникшие вызовы SVC становятся в очередь.

Какая ОЧЕРЕДЬ??? Откройте наконец-то мануал! Хватит фантазировать.
SVC - это синхронное прерывание, если оно не может быть активировано немедленно, то будет HF.

Цитата(Forger @ Jun 5 2017, 11:11) *
Я смотрю, что суть SVC понятна далеко не всем. Это как раз тот самый случай - изучить матчасть.

Вот именно.... Хватит чушь нести. Здесь не одни чайники собрались. Я думаю - много кто реально использует SVC в проектах.
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 5 2017, 09:49
Сообщение #12


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

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



Цитата(jcxz @ Jun 5 2017, 12:37) *
Вот именно....

Согласен, я поспешил с выводами sad.gif
Выходит, что в более приоритетных прерываниях нельзя использовать svc, а можно лишь в задачах/потоках. Этого я не знал ((

Я рассчитывал в реализациях программных очередей (queue) отказаться от критических секций (простое запрет/разрешение прерываний),
но коли в прерываниях это создает трудности (скажем, прерывание от usart), то выходит, что svc ипользовать не получится. А жаль ((
Или можно просто поднять приоритет svc до уровня чуть ниже важных прерываний (в которых запрещены вызовы серсвисов оси), тогда задача решится. Я прав?


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


Гуру
******

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



Цитата(Forger @ Jun 5 2017, 11:49) *
Выходит, что в более приоритетных прерываниях нельзя использовать svc, а можно лишь в задачах/потоках. Этого я не знал ((

Надо только обеспечить, чтобы в любой точке вызова SVC текущий уровень приоритета прерывания был ниже чем у SVC. И были разрешены faults. Тогда не будет HF, а будет корректный вход в ISR SVC.

Цитата(Forger @ Jun 5 2017, 11:49) *
Я рассчитывал в реализациях программных очередей (queue) отказаться от критических секций (простое запрет/разрешение прерываний),
но коли в прерываниях это создает трудности (скажем, прерывание от usart), то выходит, что svc ипользовать не получится. А жаль ((
Или можно просто поднять приоритет svc до уровня чуть ниже важных прерываний (в которых запрещены вызовы серсвисов оси), тогда задача решится. Я прав?

Можно конечно, но ещё раз спрашиваю: зачем надевать трусы через голову?? laughing.gif
Ведь если уж никак нельзя запрещать прерывания, то есть механизм LDREX/STREX, который именно для этого и создан.
А SVC - даже из названия видно - это для вызова системных функций. Привилегированных.
Можно конечно работу с очередями (или что там ещё) вынести на этот уровень, но зачем??? Это будет во много раз медленнее и громоздко чем LDREX/STREX.

Цитата(_lexa_ @ Jun 5 2017, 12:17) *
Если смотреть по коду, который я привел - первый запрос на эксклюзивный доступ здесь

А что такое "запрос на эксклюзивный доступ"? Откуда Вы это взяли?? Нет такого понятия. Нет никаких запросов там.
Эксклюзивный доступ read-modify-write - это пара инструкций LDREX/STREX работающих с некоей переменной.
Эксклюзивно - это означает, что никто другой (другой процесс) не обращается к этой переменной между LDREX и STREX. А если это условие нарушается - это нарушение эксклюзивности.
В Вашем случае есть одна только пара LDREX/STREX, её эксклюзивный доступ никто не нарушает.
Похоже Вы совсем не поняли, что написано в мануале и для чего это вообще нужно. Перечитайте ещё раз.
Go to the top of the page
 
+Quote Post
_lexa_
сообщение Jun 5 2017, 13:26
Сообщение #14


Участник
*

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



Цитата(jcxz @ Jun 5 2017, 10:59) *
А что такое "запрос на эксклюзивный доступ"? Откуда Вы это взяли?? Нет такого понятия. Нет никаких запросов там.

например, отсюда:
"PM0214. STM32F3xxx and STM32F4xxx Cortex-M4 programming manual.
2.2.7 Synchronization primitives
...
A pair of synchronization primitives comprises:
● A Load-Exclusive instruction: Used to read the value of a memory location, requesting
exclusive access
to that location."

Цитата(jcxz @ Jun 5 2017, 10:59) *
Эксклюзивный доступ read-modify-write - это пара инструкций LDREX/STREX работающих с некоей переменной.
Эксклюзивно - это означает, что никто другой (другой процесс) не обращается к этой переменной между LDREX и STREX. А если это условие нарушается - это нарушение эксклюзивности.
В Вашем случае есть одна только пара LDREX/STREX, её эксклюзивный доступ никто не нарушает.

Эта пара нужна, чтобы монитор эксклюзивного доступа отметил выполнение LDREX, затем при выполнении STREX снял эту метку, разумеется при условии, что данной парой LDREX/STREX мы не влезли между LDREX и STREX другой части программы, например в случае возникновения прерывания. Если переписать код следующим образом:
Код
void mpu_cfg_test()
{    ...
        //выполняем запрос эксклюзивного доступа к переменной cur_mes.sync
    DWORD sync=0;
    sync = __LDREX(&cur_mes.sync);
    __DMB();
    soft_int_ini();    //настойка программного прерывания
    soft_int_on();    //вызов программного прерывания
    __WFI();
    __STREX(sync, &cur_mes.sync);
}

ничего не изменится (на всякий случай я это даже проверил). Каким образом монитор эксклюзивного доступа должен увидеть, что использована именно пара LDREX/STREX
Напоминаю, это не какая-то реальная программа. Я всего лишь смоделировал ситуацию, когда после выполнения LDREX произошло прерывание и в этом прерывание производится эксклюзивный доступ к той же ячейке памяти.

Цитата(jcxz @ Jun 5 2017, 10:59) *
Похоже Вы совсем не поняли, что написано в мануале и для чего это вообще нужно. Перечитайте ещё раз.

В таком случае, если не сложно, приведите, пожалуйста, небольшой пример кода, когда происходит нарушение эксклюзивности.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 5 2017, 14:21
Сообщение #15


Гуру
******

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



Цитата(_lexa_ @ Jun 5 2017, 15:26) *
● A Load-Exclusive instruction: Used to read the value of a memory location, requesting
exclusive access
to that location."

Видимо это какое-то изобретение терминологии деятелей из STM. laughing.gif
Изучать ядро нужно по первоисточнику http://infocenter.arm.com/help/index.jsp, а не по переводам и толкованиям. А в первоисточнике нет никаких "requesting".

Цитата(_lexa_ @ Jun 5 2017, 15:26) *
ничего не изменится (на всякий случай я это даже проверил). Каким образом монитор эксклюзивного доступа должен увидеть, что использована именно пара LDREX/STREX

Вот именно в таком случае - оно и сработает и обнаружит нарушение эксклюзивности.
Команда LDREX взводит некий триггер в "1". STREX атомарно сбрасывает его и, если в в момент своего выполнения триггер стоял - выполняет операцию, если не стоял - не выполняет. И возвращает соотв. значение.
Также любое прерывание сбрасывает этот триггер. А также команда CLREX тоже сбрасывает.
Вот и всё. Всё просто.
Go to the top of the page
 
+Quote Post
scifi
сообщение Jun 5 2017, 14:31
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(jcxz @ Jun 5 2017, 17:21) *
Изучать ядро нужно по первоисточнику http://infocenter.arm.com/help/index.jsp, а не по переводам и толкованиям. А в первоисточнике нет никаких "requesting".

В первоисточнике немного намудрили, так как объясняют концепцию применительно к многопроцессорным системам в том числе, а там несколько сложнее.
тынц
тынц
Go to the top of the page
 
+Quote Post
AVI-crak
сообщение Jun 5 2017, 17:37
Сообщение #17


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

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



Начали за упокой, кончили за здравие.

Как уже было сказано, LDREX выставляет атомарный флаг при использовании команды в потоке, конкретно на используемый адрес. Точнее конкретный адрес чтения выставляется на мониторе, и отслеживается аппаратными механизмами сразу на интерфейсе памяти.
Атомарный флаг может сбросить любое прерывание, любое аппаратное чтение/запись по этому адресу (например DMA).
Флаг не сбрасывается в момент применения команды LDREX в прерывании и перебивании его более высоким приоритетом. Отчего костыль для использования в прерывании содержит собственный сброс до и после.
STREX выполняется, или не выполняется без использования программной проверки атомарного флага, этот механизм выполнен полностью аппаратно.
STREX выдаёт флаг, видимый для программы - для проверки успешности операции.

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

+Ещё один важный прикол - конвейер. Лучше перебздеть, и подтверждать полный сброс данных в память.
+Ещё грабли - LDREX STREX могут применяться на той памяти, что имеет прямое подключение к ядру мк. Например в М7 часть памяти заведена через ускоритель, в результате применение LDREX STREX моментально вешает мк.

------------

SVC - безусловное прерывание. Отрабатывается без вытеснения из любой позиции. Перебить SVC - просто невозможно.
SVC - это рыба для сервисов ОС, с небольшим количеством шаманства - превращается в очень удобную функцию.
У меня на SVC полностью работает собственная ось.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 5 2017, 21:35
Сообщение #18


Гуру
******

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



Цитата(AVI-crak @ Jun 5 2017, 19:37) *
Как уже было сказано, LDREX выставляет атомарный флаг при использовании команды в потоке, конкретно на используемый адрес. Точнее конкретный адрес чтения выставляется на мониторе, и отслеживается аппаратными механизмами сразу на интерфейсе памяти.
Атомарный флаг может сбросить любое прерывание, любое аппаратное чтение/запись по этому адресу (например DMA).

Монитор эксклюзивного доступа не контролирует адрес. Об этом явно сказано в мануале.
Да и как вы это себе представляете? Если у процессора 4гига адресное пространство - это-ж нужна 4^32 триггеров иметь в CPU - для каждого адреса.
Опять-же - любое чтение/запись не может и не должно. Может только STREX, CLREX или любое изменение текущего уровня прерывания.
DMA, как и прочие bus-master-ы, тоже не должны влиять - они не относятся к ядру процессора.

Цитата(_lexa_ @ Jun 5 2017, 19:40) *
т.к. любое прерывание сбрасывает тег монитор и все дальнейшее выполнение программы происходит, как будто LDREX до этого не выполнялась.

И что???
Так в этом и заключается вся полезность LDREX/STREX! Именно для того оно и предназначено - если между LDREX и STREX было прерывание (или переключение контекста, которое тоже выполняется через прерывание), то значит - нет гарантии, что операция чтение-модификация-запись была эксклюзивной.
Похоже Вы так и не поняли зачем нужен и как работает этот эксклюзивный доступ... sad.gif

Цитата(_lexa_ @ Jun 5 2017, 19:40) *
Бесполезность LDREX/STREX для синхронизации косвенно подтверждается еще и тем, что в CMSIS-RTOS эти команды в мутексах и семафорах не используются.

Они и не должны там использоваться если ОС должна быть мультиплатформенной. Они могут использоваться в портах ОС.
Понятно - все дураки, и создатели ядра и создатели IAR-а например, да все кто поддерживает эти LDREX/STREX - не понимают они их бесполезность. Объясните им biggrin.gif

Цитата(AVI-crak @ Jun 5 2017, 20:00) *
Нет широкого распространения по другой причине - память должна подключаться к ядру без цепочек ускорителей. То-есть команды LDREX/STREX гарантированно выполняются на всех arm чипах, но не на всей используемой памяти.

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

Цитата(KnightIgor @ Jun 5 2017, 21:42) *
Что будет, если после сохранения текущего статуса разрешения прерываний в выделеной переменной (оно было разрешено), но до исполнения самой инструкции запрета прерывания произойдет-таки прерывание, которое по какой-либо логике всей программы запретит прерывания? Как я понимаю, после выхода из критической секции прерывание будет-таки разрешено , т.к. будет восстановлено из переменной?

Ну наверное.
А что это за прерывание такое, которое внутри себя запрещает прерывания??? Аппаратное асинхронное?
Т.е. - оно может вызваться в любой точке и в произвольный момент времени запретить прерывания?
А зачем это нужно и как может такая программа вообще функционировать?
Go to the top of the page
 
+Quote Post
AVI-crak
сообщение Jun 6 2017, 07:24
Сообщение #19


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

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



Цитата(jcxz @ Jun 6 2017, 03:35) *
Монитор эксклюзивного доступа не контролирует адрес. Об этом явно сказано в мануале.
Да и как вы это себе представляете? Если у процессора 4гига адресное пространство - это-ж нужна 4^32 триггеров иметь в CPU - для каждого адреса.

Там всё просто, один единственный 32b регистр и схема сравнения на коммутаторе памяти, уже после арбитра и коммутатора нагрузки. Эти команды не выполняются целиком и полностью в ядре мк, они большей частью размазаны по всему кристаллу.
Точно так-же как и команды DSB, ISB, ISB, WFE, и так далее.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 6 2017, 08:20
Сообщение #20


Гуру
******

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



Цитата(AVI-crak @ Jun 6 2017, 09:24) *
Там всё просто, один единственный 32b регистр и схема сравнения на коммутаторе памяти, уже после арбитра и коммутатора нагрузки. Эти команды не выполняются целиком и полностью в ядре мк, они большей частью размазаны по всему кристаллу.

Открываем мануал на M4, читаем:
"The Cortex-M4 processor implements a local exclusive monitor. The local monitor within the processor
has been constructed so that it does not hold any physical address, but instead treats any access as
matching the address of the previous LDREX
. This means that the implemented exclusives reservation
granule is the entire memory address range."
Фантазии про некий регистр рассеиваются laughing.gif
Влияние доступов от DMA и прочих bus-masters на exclusive monitor - также представляется крайне сомнительным, так как:
1. зачем оно нужно?
2. где про это сказано?
3. exclusive monitor относится к ядру, а DMA- и прочие bus-masters к ядру не относятся и у каждого МК-мэйкера свои.
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- _lexa_   __LDREX __STREX в STM32F407   Jun 4 2017, 13:18
|||- - AHTOXA   Цитата(Forger @ Jun 5 2017, 13:17) Полага...   Jun 5 2017, 08:22
||||- - Forger   Цитата(AHTOXA @ Jun 5 2017, 11:22) Если, ...   Jun 5 2017, 08:24
||||- - AHTOXA   Цитата(Forger @ Jun 5 2017, 13:24) Почему...   Jun 5 2017, 08:54
|||- - Forger   Цитата(jcxz @ Jun 5 2017, 13:50) Надо тол...   Jun 5 2017, 11:00
||||- - jcxz   Цитата(Forger @ Jun 5 2017, 13:00) Не пон...   Jun 5 2017, 11:09
||||- - Forger   Цитата(jcxz @ Jun 5 2017, 14:09) Так как ...   Jun 5 2017, 11:18
||||- - Forger   Попался полезный документ по теме: http://infocent...   Jun 5 2017, 12:22
|||||- - _lexa_   Цитата(Forger @ Jun 5 2017, 12:22) Попалс...   Jun 5 2017, 13:55
||||- - jcxz   Цитата(Forger @ Jun 5 2017, 13:18) Речь к...   Jun 5 2017, 13:47
|||- - AHTOXA   Цитата(_lexa_ @ Jun 5 2017, 18:26) В тако...   Jun 5 2017, 13:51
||||- - _lexa_   Цитата(jcxz @ Jun 5 2017, 21:35) Похоже В...   Jun 5 2017, 23:19
|||||- - _lexa_   Цитата(jcxz @ Jun 6 2017, 08:20) Открывае...   Jun 6 2017, 20:56
|||||- - Alechek   Цитата(jcxz @ Jun 6 2017, 13:20) Фантазии...   Jun 7 2017, 08:31
|||||- - jcxz   Цитата(Alechek @ Jun 7 2017, 10:31) Опять...   Jun 7 2017, 08:56
||||- - KnightIgor   Цитата(jcxz @ Jun 5 2017, 22:35) Ну навер...   Jun 6 2017, 10:22
||||- - AVI-crak   Цитата(jcxz @ Jun 6 2017, 14:20) 1. зачем...   Jun 6 2017, 11:02
|||||- - KnightIgor   Цитата(AVI-crak @ Jun 6 2017, 12:02)...   Jun 6 2017, 20:34
|||||- - jcxz   Цитата(KnightIgor @ Jun 6 2017, 22:34) Ра...   Jun 6 2017, 21:36
|||||- - LightElf   QUOTE (jcxz @ Jun 7 2017, 00:36) Я писал ...   Jun 7 2017, 11:52
|||||- - Forger   Цитата(LightElf @ Jun 7 2017, 14:52) А пр...   Jun 7 2017, 12:39
|||||- - jcxz   Цитата(Forger @ Jun 7 2017, 14:39) Причем...   Jun 7 2017, 13:13
|||||- - Forger   Цитата(jcxz @ Jun 7 2017, 16:13) чтобы, е...   Jun 7 2017, 13:27
||||- - jcxz   Цитата(KnightIgor @ Jun 6 2017, 12:22) То...   Jun 6 2017, 12:08
|||- - _lexa_   Цитата(jcxz @ Jun 5 2017, 14:21) Видимо э...   Jun 5 2017, 17:40
|||- - AVI-crak   Цитата(_lexa_ @ Jun 5 2017, 23:40) Спасиб...   Jun 5 2017, 18:00
|||- - _lexa_   Цитата(AVI-crak @ Jun 5 2017, 18:00)...   Jun 5 2017, 19:28
||- - KnightIgor   Цитата(AHTOXA @ Jun 5 2017, 06:38) А в чё...   Jun 5 2017, 12:40
||- - jcxz   Цитата(KnightIgor @ Jun 5 2017, 14:40) Ес...   Jun 5 2017, 13:57
|||- - KnightIgor   Цитата(jcxz @ Jun 5 2017, 14:57) У меня ...   Jun 5 2017, 19:42
||- - AHTOXA   Цитата(KnightIgor @ Jun 5 2017, 17:40) Ка...   Jun 5 2017, 13:58
|- - jcxz   Цитата(_lexa_ @ Jun 4 2017, 20:39) Где-то...   Jun 5 2017, 07:49
|- - _lexa_   Цитата(jcxz @ Jun 5 2017, 07:49) Если меж...   Jun 5 2017, 10:17
|- - Alechek   ЦитатаНе тот мануал открываете Ну почему же не тот...   Jun 7 2017, 09:18
|- - jcxz   Цитата(Alechek @ Jun 7 2017, 11:18) Про у...   Jun 7 2017, 09:29
|- - Alechek   Цитата(jcxz @ Jun 7 2017, 14:29) В смысле...   Jun 7 2017, 10:21
|- - scifi   Цитата(Alechek @ Jun 7 2017, 13:21) В смы...   Jun 7 2017, 10:27
|- - jcxz   Цитата(Alechek @ Jun 7 2017, 12:21) В смы...   Jun 7 2017, 11:23
- - Alechek   Цитата(scifi @ Jun 7 2017, 15:27) Это наз...   Jun 7 2017, 12:22
|- - scifi   Цитата(Alechek @ Jun 7 2017, 15:22) Сдела...   Jun 7 2017, 12:50
|- - AHTOXA   Цитата(Alechek @ Jun 7 2017, 17:22) А поп...   Jun 7 2017, 13:30
- - Alechek   AHTOXA, спасибо, ознакомился. Но, опять противореч...   Jun 8 2017, 05:01
|- - jcxz   Цитата(Alechek @ Jun 8 2017, 07:01) - LDR...   Jun 8 2017, 06:17
|- - AHTOXA   Цитата(Alechek @ Jun 8 2017, 10:01) - LDR...   Jun 8 2017, 06:21
|- - LightElf   QUOTE (AHTOXA @ Jun 8 2017, 09:21) Именно...   Jun 8 2017, 13:44
|- - AHTOXA   Цитата(LightElf @ Jun 8 2017, 18:44) Есть...   Jun 8 2017, 14:52
- - Alechek   Цитата(jcxz @ Jun 8 2017, 11:17) И правил...   Jun 8 2017, 11:54
- - AVI-crak   Проверять нужно кодом на асме, чтобы gcc не наопти...   Jun 8 2017, 13:21
|- - jcxz   Цитата(AVI-crak @ Jun 8 2017, 15:21)...   Jun 8 2017, 20:32
|- - Forger   Коли SVC синхронное и его не получиться использова...   Jun 9 2017, 07:50
|- - jcxz   Цитата(Forger @ Jun 9 2017, 09:50) зы. Пр...   Jun 9 2017, 10:33
|- - Forger   Цитата(jcxz @ Jun 9 2017, 13:33) PendSV н...   Jun 9 2017, 10:58
|- - Шаманъ   Цитата(Forger @ Jun 9 2017, 13:58) как сд...   Jun 9 2017, 13:02
|- - Forger   Цитата(Шаманъ @ Jun 9 2017, 16:02) Очеред...   Jun 9 2017, 13:20
|- - Шаманъ   Цитата(Forger @ Jun 9 2017, 16:20) хочетс...   Jun 9 2017, 14:14
||- - Forger   Цитата(Шаманъ @ Jun 9 2017, 17:14) Интере...   Jun 9 2017, 14:30
||- - Шаманъ   Цитата(Forger @ Jun 9 2017, 17:30) При че...   Jun 9 2017, 15:40
||- - Forger   Цитата(Шаманъ @ Jun 9 2017, 18:40) Это ка...   Jun 9 2017, 16:27
||- - Шаманъ   Цитата(Forger @ Jun 9 2017, 19:27) Я гово...   Jun 9 2017, 17:08
||- - Forger   Цитата(Шаманъ @ Jun 9 2017, 20:08) От же ...   Jun 9 2017, 17:23
||- - Шаманъ   Цитата(Forger @ Jun 9 2017, 20:23) Чтобы ...   Jun 9 2017, 17:40
|||- - Forger   Цитата(Шаманъ @ Jun 9 2017, 20:40) Если н...   Jun 9 2017, 17:48
|||- - Шаманъ   Цитата(Forger @ Jun 9 2017, 20:48) Не, эт...   Jun 9 2017, 17:56
|||- - Forger   Цитата(Шаманъ @ Jun 9 2017, 20:56) Конечн...   Jun 9 2017, 18:04
|||- - Шаманъ   Цитата(Forger @ Jun 9 2017, 21:04) И само...   Jun 9 2017, 18:54
|||- - jcxz   Цитата(Forger @ Jun 9 2017, 20:04) Я дела...   Jun 9 2017, 19:37
|||- - Forger   Цитата(jcxz @ Jun 9 2017, 22:31) Вот как ...   Jun 9 2017, 19:39
||||- - jcxz   Цитата(Forger @ Jun 9 2017, 21:39) Самое ...   Jun 9 2017, 20:27
|||- - Forger   Цитата(jcxz @ Jun 9 2017, 22:37) Допустим...   Jun 9 2017, 20:44
|||- - jcxz   Цитата(Forger @ Jun 9 2017, 22:44) Понима...   Jun 9 2017, 20:58
||||- - Forger   Цитата(jcxz @ Jun 9 2017, 23:58) К работе...   Jun 9 2017, 21:15
||||- - jcxz   Цитата(Forger @ Jun 9 2017, 23:15) Пусть ...   Jun 9 2017, 21:20
|||||- - Forger   Цитата(jcxz @ Jun 10 2017, 00:17) Ещё раз...   Jun 9 2017, 21:20
|||||- - Forger   Цитата(jcxz @ Jun 10 2017, 00:20) Да хоть...   Jun 9 2017, 21:27
||||- - jcxz   Цитата(Forger @ Jun 9 2017, 23:15) При че...   Jun 9 2017, 21:24
|||- - Forger   Кстати, при очистке очереди изменяются оба указате...   Jun 9 2017, 20:59
|||- - jcxz   Цитата(Forger @ Jun 9 2017, 22:59) Кстати...   Jun 9 2017, 21:10
||- - jcxz   Цитата(Forger @ Jun 9 2017, 19:23) А в фо...   Jun 9 2017, 19:18
||- - Forger   Цитата(jcxz @ Jun 9 2017, 22:12) И в фоно...   Jun 9 2017, 19:18
|- - AVI-crak   Защищённый режим: стек для потоков psp, стек для п...   Jun 9 2017, 14:38
- - AHTOXA   Цитата(Alechek @ Jun 8 2017, 16:54) Вобще...   Jun 8 2017, 13:39
2 страниц V   1 2 >


Reply to this topicStart new topic
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0

 


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


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