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

 
 
> __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   1 2 3 > »   
Start new topic
Ответов (1 - 99)
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
jcxz
сообщение Jun 5 2017, 07:49
Сообщение #8


Гуру
******

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



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

Если между LDREX и STREX произошло прерывание или был выполнен другой эксклюзивный доступ, до будет нарушение эксклюзивности.
Ну и где у вас между LDREX и STREX нарушение эксклюзивности?

Цитата(KnightIgor @ Jun 4 2017, 23:14) *
// SVC_Handler used for "atomic" operations based on the the fact, that
// SVC handler cannot be interrupted by higher placed interrupts.

Жесть какая. Вот уж действительно - одевание трусов через голову biggrin.gif
Чем способы: LDREX/STREX или запрет прерываний не угодили? Они в разы менее громоздки.
А для SVC можно придумать гораздо более полезные применения.
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 5 2017, 08:17
Сообщение #9


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

Группа: Свой
Сообщений: 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
AHTOXA
сообщение Jun 5 2017, 08:22
Сообщение #10


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

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



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

Если, как пишет, KnightIgor, svc является непрерываемым, то чем это отличается от запрета остальных прерываний?


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


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

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



Цитата(AHTOXA @ Jun 5 2017, 11:22) *
Если, как пишет, KnightIgor, svc является непрерываемым, то чем это отличается от запрета остальных прерываний?

Почему непрерывный? Любое более приоритетное прерывание может его прервать в любой момент, иначе от этого SVC почти нет никакого проку .
Лишь нужно правильно настроить NVIC.
Причем, это более "мощное" прерывание может вызвать это же самое SVC, а когда выйдет, продолжится обработка прерванного SVC, и после его завершения тут же опять вызовется новое, отложенное.
Так по сути SVC дает гарантию целостности кусков кода.
Безусловно, оверхед заметно растет, но цена этому - гарантия реакции на действительно важные события.
Под SVC вообще идеально ложатся все сервисы RTOS, судя по всему прям для них SVC и задумывалось.
Только вот мне не попадались готовые оси, где это используется ...


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


Гуру
******

Группа: Свой
Сообщений: 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
AHTOXA
сообщение Jun 5 2017, 08:54
Сообщение #13


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

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



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

Ну вы хоть читайте, на что отвечаете...

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

Видите, "благодаря непрерываемости SVC". Это значит, что у svc в его случае самый высокий приоритет. А значит, вход в обработчик SVC блокирует остальные прерывания. Вот я и поинтересовался:
Цитата(AHTOXA @ Jun 5 2017, 10:38) *
А в чём выгода такого метода по сравнению с простым запретом/разрешением прерываний?

А теперь вы спрашиваете, "почему непрерывный".
Теперь понимаете нить?


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


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

Группа: Свой
Сообщений: 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
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 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
Сообщение #16


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

Группа: Свой
Сообщений: 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
_lexa_
сообщение Jun 5 2017, 10:17
Сообщение #17


Участник
*

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



Цитата(jcxz @ Jun 5 2017, 07:49) *
Если между LDREX и STREX произошло прерывание или был выполнен другой эксклюзивный доступ, до будет нарушение эксклюзивности.
Ну и где у вас между LDREX и STREX нарушение эксклюзивности?


Если смотреть по коду, который я привел - первый запрос на эксклюзивный доступ здесь:
CODE
void mpu_cfg_test()
{ ...
//выполняем запрос эксклюзивного доступа к переменной 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);
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 5 2017, 10:59
Сообщение #18


Гуру
******

Группа: Свой
Сообщений: 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
Forger
сообщение Jun 5 2017, 11:00
Сообщение #19


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

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



Цитата(jcxz @ Jun 5 2017, 13:50) *
Надо только обеспечить, чтобы в любой точке вызова SVC текущий уровень приоритета прерывания был ниже чем у SVC.

Это решаемо, просто, запрещается вызов SVC в критичных прерываниях, где запрещен вызов сервисов оси (соотв. assert).

Цитата
И были разрешены faults. Тогда не будет HF, а будет корректный вход в ISR SVC.

Не понял ((( Т.е. запрещенные faults нарушают нормальную работу SVC?


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


Гуру
******

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



Цитата(Forger @ Jun 5 2017, 13:00) *
Не понял ((( Т.е. запрещенные faults нарушают нормальную работу SVC?

Естественно. Я же писал уже несколько раз:
Цитата(jcxz @ Jun 5 2017, 11:37) *
Если бы Вы открыли мануал на ядро, то узнали бы, что SVC является синхронным исключением. Т.е. - должно обработаться сразу же.
А если это не возможно (например - запрещены исключения или, как Вы советуете, оно вызвано внутри более приоритетного ISR), то будет активирован механизм эскалации до Hard Fault.

Ещё раз: если SVC по каким-то причинам не может быть активировано немедленно, будет эскалация до HF.
Считайте что SVC - это вызов функции. Если у Вас в коде идёт команда BL, то ведь процессор обязан её выполнить, он не может её перескочить.
То же самое и с SVC - это считается вызовом системной функции. Она не может быть не выполнена. А если запрещены fault-ы - значит активировать исключение нельзя. Из-за этого конфликта и будет эскалация до HardFault. Процессор будет стоять на SVC и повышать-повышать приоритет её до тех пор, пока не сможет выполнить. Он и повысит до HF, которое может выполнить даже с запрещёнными fault-ами.
Так как это синхронное прерывание, значит оно должно быть выполнено немедленно.
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 5 2017, 11:18
Сообщение #21


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

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



Цитата(jcxz @ Jun 5 2017, 14:09) *
Так как это синхронное прерывание, значит оно должно быть выполнено немедленно.

Цитата(jcxz @ Jun 5 2017, 14:09) *
И были разрешены faults.

Речь как я понял идет про конкретно один fault - SVCall Handler. Или я опять не так понял?




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


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

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



Попался полезный документ по теме:
http://infocenter.arm.com/help/topic/com.a..._primitives.pdf


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


Знающий
****

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



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

Я не претендую на истину в последней инстанции и рассматриваю применение SVC в моих проектах как один из методов программирования с использованием предоставленных возможностей процессора. Ноги где-то растут из старых времен MS DOS и использованием INT 2F wink.gif.

Как кто-то в теме догадался, не люблю я всякие запреты-разрешения прерываний. Зачем меня должно в участке кода заботить, какие разрешены, а какие нет? Если работать с запретом и последующим разрешением общего прерывания, надо тоже хоть немного контекст сохранять: надо бы знать, а было ли вообще разрешено прерывание на момент необходимости его запрета, чтобы потом не разрешить случаем то, что было запрещено? Затем необходимо множить такие блоки во всех фрагментах, которые критическую секцию используют: хоть макросы напиши, код получается громоздкий для написания и понимания. Не нравится мне это чисто стилистически. На круг получится, что суммарный код обрамления критических секций станет больше обработчика SVC. Синтаксически - как следует из заголовка, который я привел, - я работаю с на вид обычными функциями, которые порождают единственную инструкцию.

И еще. Тут многие забалованы F4xx и выше. А у меня есть проекты на одной плате с опциональными F103 и F051 (ценообразование). Вы будете смеяться, но на Cortex-M0 F051 LDREX/STREX отсутствуют. А механизм SVC работает на обоих.

Сообщение отредактировал KnightIgor - Jun 5 2017, 12:50
Go to the top of the page
 
+Quote Post
_lexa_
сообщение Jun 5 2017, 13:26
Сообщение #24


Участник
*

Группа: Участник
Сообщений: 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, 13:47
Сообщение #25


Гуру
******

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



Цитата(Forger @ Jun 5 2017, 13:18) *
Речь как я понял идет про конкретно один fault - SVCall Handler. Или я опять не так понял?

Бит разрешения на все fault-ы один общий.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 5 2017, 13:51
Сообщение #26


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

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



Цитата(_lexa_ @ Jun 5 2017, 18:26) *
В таком случае, если не сложно, приведите, пожалуйста, небольшой пример кода, когда происходит нарушение эксклюзивности.

Вот тут посмотрите: тынц. И вообще всю тему посмотрите. Там очень подробно всё разобрали, с учётом особенностей STM32.


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


Участник
*

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



Цитата(Forger @ Jun 5 2017, 12:22) *
Попался полезный документ по теме:
http://infocenter.arm.com/help/topic/com.a..._primitives.pdf


Я тоже его нашел, сейчас как раз изучаю. Тема также освещена в ARMv7-M Architecture Reference Manual, где среди прочего написано про разделяемую память, про глобальный и локальный мониторы эксклюзивного доступа, многопроцессорность и т.д. Все эти документы ARM-овские.
У ST LDREX/STREX описаны в PM0214. STM32F3xxx and STM32F4xxx Cortex-M4 programming manual. Причем довольно коротко, многое не по какой-то причине не затронуто и даже ссылок на АРМ-овские документы не даны.
В общем, поизучав все это приходит мысль, что я просто в каком-то регистре не поставил какой-то флаг и у меня, например, не работает глобальный монитор.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 5 2017, 13:57
Сообщение #28


Гуру
******

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



Цитата(KnightIgor @ Jun 5 2017, 14:40) *
Если работать с запретом и последующим разрешением общего прерывания, надо тоже хоть немного контекст сохранять: надо бы знать, а было ли вообще разрешено прерывание на момент необходимости его запрета, чтобы потом не разрешить случаем то, что было запрещено?

void f1()
{
CPU_SR_ALLOCATE(); //выделение переменной (регистра) для сохранения состояния прерываний
ENTR_CRT_SECTION(); //вход в критическую секцию (запрет прерываний)
...
EXIT_CRT_SECTION(); //выход из критической секции (восстановление состояния прерываний)
}
void f2()
{
CPU_SR_ALLOCATE(); //выделение переменной (регистра) для сохранения состояния прерываний
ENTR_CRT_SECTION(); //вход в критическую секцию (запрет прерываний)
f1();
...
EXIT_CRT_SECTION(); //выход из критической секции (восстановление состояния прерываний)
f1();
}
Вот и всё отслеживание. Больше никаких проверок не нужно и можно вызывать сколько угодно вложенно - всё работает корректно.
ENTR_CRT_SECTION() - компилится в 2 команды CPU;
EXIT_CRT_SECTION() - компилится в 1 команду CPU.
Теперь сравните со своим огородом в десятки команд.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 5 2017, 13:58
Сообщение #29


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

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



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


Ох, ну вот уж проблема так проблема sm.gif
Это может выглядеть, например, просто как объявление
Код
{
    TCritSect cs;
    ...
}

в начале блока кода. При выходе из блока прерывания автоматически возвращаются в исходное состояние.

Я не говорю, что ваш способ ошибочен, я говорю, что он не даёт преимуществ по сравнению с простым запретом/разрешением прерываний, и к тому же он (гораздо) медленнее. Думаю, что на маленьких процессорах (типа M0(+)) это может быть критично.
Кроме того, как тут выяснили, этот способ требует правильной расстановки приоритетов, а иначе способен вызвать HardFault.


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


Гуру
******

Группа: Свой
Сообщений: 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
Сообщение #31


Гуру
******

Группа: Свой
Сообщений: 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
Сообщение #32


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

Группа: Участник
Сообщений: 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
_lexa_
сообщение Jun 5 2017, 17:40
Сообщение #33


Участник
*

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



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


Вот в первоисточнике ARMv7-M Architecture Reference Manual:
A3.4.2 Exclusive access instructions and Shareable memory regions.
Operation of the global monitor.
Load-Exclusive from Shareable memory performs a load from memory, and causes the physical address of
the access to be tagged as exclusive access for the requesting processor (эксклюзивный доступ для запрашивающего процессора)

Да и как не читать? Это целевой мануал, для процессора с которым я работаю.

Цитата(jcxz @ Jun 5 2017, 14:21) *
Вот именно в таком случае - оно и сработает и обнаружит нарушение эксклюзивности.
Команда LDREX взводит некий триггер в "1". STREX атомарно сбрасывает его и, если в в момент своего выполнения триггер стоял - выполняет операцию, если не стоял - не выполняет. И возвращает соотв. значение.
Вот и всё. Всё просто.

Именно так я себе все это и представлял.

Цитата(AHTOXA @ Jun 5 2017, 13:51) *
Вот тут посмотрите: тынц. И вообще всю тему посмотрите. Там очень подробно всё разобрали, с учётом особенностей STM32.

Спасибо за ссылку. Узнал много интересного.

Сообщение отредактировал _lexa_ - Jun 5 2017, 22:22
Go to the top of the page
 
+Quote Post
AVI-crak
сообщение Jun 5 2017, 18:00
Сообщение #34


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

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



Цитата(_lexa_ @ Jun 5 2017, 23:40) *
Спасибо за ссылку. Узнал много интересного. В частности, что LDREX/STREX, по крайней мере для STM32 на cortex-m4, не могут использоваться для синхронизации доступа к памяти, т.к. любое прерывание сбрасывает тег монитор и все дальнейшее выполнение программы происходит, как будто LDREX до этого не выполнялась. Бесполезность LDREX/STREX для синхронизации косвенно подтверждается еще и тем, что в CMSIS-RTOS эти команды в мутексах и семафорах не используются.


Сброс тег монитора из потока в прерывание - это нормальное поведение LDREX/STREX, именно для этого они и задумывались.
Нет широкого распространения по другой причине - память должна подключаться к ядру без цепочек ускорителей. То-есть команды LDREX/STREX гарантированно выполняются на всех arm чипах, но не на всей используемой памяти. Делить на можно/нельзя - слишком сложно, проще не использовать вовсе. Однако применение LDREX/STREX даёт очень ощутимое ускорение на операциях с атомарными флагами. Словом можно - если руки растут из нужного места.
Весь смысл в том чтобы не испортить другие флаги.
Go to the top of the page
 
+Quote Post
_lexa_
сообщение Jun 5 2017, 19:28
Сообщение #35


Участник
*

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



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

Пожалуй я в самом деле погорячился по поводу невозможности синхронизации с помощью LDREX/STREX.
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Jun 5 2017, 19:42
Сообщение #36


Знающий
****

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



Цитата(jcxz @ Jun 5 2017, 14:57) *

У меня вопросы по Вашему примеру.
Что будет, если после сохранения текущего статуса разрешения прерываний в выделеной переменной (оно было разрешено), но до исполнения самой инструкции запрета прерывания произойдет-таки прерывание, которое по какой-либо логике всей программы запретит прерывания? Как я понимаю, после выхода из критической секции прерывание будет-таки разрешено , т.к. будет восстановлено из переменной?

Сообщение отредактировал KnightIgor - Jun 5 2017, 19:45
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 5 2017, 21:35
Сообщение #37


Гуру
******

Группа: Свой
Сообщений: 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
_lexa_
сообщение Jun 5 2017, 23:19
Сообщение #38


Участник
*

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



Цитата(jcxz @ Jun 5 2017, 21:35) *
Похоже Вы так и не поняли зачем нужен и как работает этот эксклюзивный доступ... sad.gif

AVI-crak доходчиво объяснил:
Цитата(AVI-crak @ Jun 5 2017, 18:00) *
Сброс тег монитора из потока в прерывание - это нормальное поведение LDREX/STREX, именно для этого они и задумывались.


Цитата(jcxz @ Jun 5 2017, 21:35) *
Они и не должны там использоваться если ОС должна быть мультиплатформенной. Они могут использоваться в портах ОС.
Понятно - все дураки, и создатели ядра и создатели IAR-а например, да все кто поддерживает эти LDREX/STREX - не понимают они их бесполезность. Объясните им biggrin.gif

Я же чуть ниже написал, что погорячился. И сообщение поправил, чтоб глаза не резало.
Go to the top of the page
 
+Quote Post
AVI-crak
сообщение Jun 6 2017, 07:24
Сообщение #39


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

Группа: Участник
Сообщений: 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
Сообщение #40


Гуру
******

Группа: Свой
Сообщений: 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
KnightIgor
сообщение Jun 6 2017, 10:22
Сообщение #41


Знающий
****

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



Цитата(jcxz @ Jun 5 2017, 22:35) *
Ну наверное.

То есть, предложенное решение не на все случаи? Вы также признаете очевидность, Мистер Андерсон? wink.gif

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

Да кто же его знает! Однако, такое возможно. Например, прерывание, сделав дело и установив флаг, запрещает прерывания до момента, пока синхронная часть не обработает флаг и не сочтет нужным прерывание снова разрешить. И Ваш код породит огород, на котором пожнут не то, что сеяли.

Сообщение отредактировал KnightIgor - Jun 6 2017, 10:22
Go to the top of the page
 
+Quote Post
AVI-crak
сообщение Jun 6 2017, 11:02
Сообщение #42


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

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



Цитата(jcxz @ Jun 6 2017, 14:20) *
1. зачем оно нужно?
2. где про это сказано?
3. exclusive monitor относится к ядру, а DMA- и прочие bus-masters к ядру не относятся и у каждого МК-мэйкера свои.

Это результат проверки с отладчиком на реальном камне М3-7. В последнее время я чаще доверяю собственным экспериментам, чем расплывчатому переводу гугла.
Кстати, чтобы убрать последствия действий самого отладчика - точки останова необходимо ставить за пределами тестовой функции, иначе будут увлекательные результаты.


Цитата(KnightIgor @ Jun 6 2017, 16:22) *
Да кто же его знает! Однако, такое возможно. Например, прерывание, сделав дело и установив флаг, запрещает прерывания до момента


Находясь в прерывании нельзя запретить само прерывание, получите сбой. Однако можно сбросить те сработавшие прерывания - что имеют более низкий приоритет, те что находятся в ожидании. Но не те что уже сработали и были вытеснены. Иначе будет разрушение стека.
Кстати, эти действия могут понадобится в случае просто огромного кода в теле прерывания. То-есть нужно сначала создать себе проблемы, и только потом героически их решать.
Юзайте SVC, и будет вам счастье.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 6 2017, 12:08
Сообщение #43


Гуру
******

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



Цитата(KnightIgor @ Jun 6 2017, 12:22) *
То есть, предложенное решение не на все случаи? Вы также признаете очевидность, Мистер Андерсон? wink.gif

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

Цитата(KnightIgor @ Jun 6 2017, 12:22) *
Да кто же его знает! Однако, такое возможно. Например, прерывание, сделав дело и установив флаг, запрещает прерывания до момента, пока синхронная часть не обработает флаг и не сочтет нужным прерывание снова разрешить. И Ваш код породит огород, на котором пожнут не то, что сеяли.

Вы сами-то хоть верите в то, что пишете? У Вас реально были такие алгоритмы? Или может у кого-то из здесь присутствующих (чайников не считаем)?
Конечно - можно лисапет и с 5-ю колёсами изобрести. Ездить будет? Ну а почему бы и нет. Нужно это кому-то реально? Вопрос риторический.
А если на дороге встретится 2 ямки - лисапет с 2-я колёсами ведь в них провалится, а с 5-ю - нет! Это значит что 2-колёсный лисапет никуда не годится и все кто на нём ездят - идиоты, а кто на 5-колёсном - умные?
И можно ещё напридумывать кучу причин, почему 2-колёсный плох. Только все почему-то на нём ездят и не жужжат, а у Вас - не получается никак и Вам обязательно нужен 5-колёсный laughing.gif

Цитата(AVI-crak @ Jun 6 2017, 13:02) *
эти действия могут понадобится в случае просто огромного кода в теле прерывания.

В этом случае надо просто перенести этот код в задачу ОС и всё.
Да и без ОС можно решить задачу нормально: возбудив программное прерывание с меньшим приоритетом и продолжив работу там, отпустив аппаратный ISR.
Как видно - для всего есть штатные решения, а необходимость запрета прерываний внутри ISR - высосана из пальца.

Цитата(AVI-crak @ Jun 6 2017, 13:02) *
Это результат проверки с отладчиком на реальном камне М3-7. В последнее время я чаще доверяю собственным экспериментам, чем расплывчатому переводу гугла.

А зачем Вам нужно, чтобы DMA-операция влияла на монитор эксклюзивности? Ну т.е. - реально, а не по надуманным причинам?
Go to the top of the page
 
+Quote Post
KnightIgor
сообщение Jun 6 2017, 20:34
Сообщение #44


Знающий
****

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



Цитата(AVI-crak @ Jun 6 2017, 12:02) *
Юзайте SVC, и будет вам счастье.

Это не по адресу: я и так юзаю - почитайте сначала. Меня отговаривают и предлагают варианты, которые не всегда работоспособны.
Цитата
Находясь в прерывании нельзя запретить само прерывание, получите сбой.

Я предполагаю, что это Вы сгоряча. Очень даже легко можно запретить прерывание, находясь в нем. Без последствий.

Цитата(jcxz @ Jun 6 2017, 13:08) *
Для каких-то высосанных из пальца случае разве что. Для реальных задач из жизни - бесполезно.

Почитайте Мерфи: если что-то может случиться, оно случится.
Цитата
Вы сами-то хоть верите в то, что пишете?

Инженерная наука не оперирует понятием веры. Есть факты, есть опыт. ОТ: правда, слышал, что ныне за такое высказывание в РФ и сесть можно.
Цитата
Как видно - для всего есть штатные решения, а необходимость запрета прерываний внутри ISR - высосана из пальца.

Утверждение более чем недальновидное.
Рассмотрим пример. Сразу оговорюсь, что речь не о глобальном запрете прерывания, а о запрете периферийного. Но и Вы пишете об ISR вообще.

В прерывании от устройства обнаруживается, что буфер приема заполнен, т.е. недовыбран синхронным циклом. Есть два варианта: выбросить данные или таки еще немного подождать, дать возможность выбрать, тем более, что передача данных по каналу сама по себе требует времени, и можно успеть до переполнения периферийного регистра. Одно из решений: запретить прерывание, оставив флаг, выйти, дать синхронному циклу поработать. Синхронный цикл после выбоки данных просто разрешает прерывание снова. Поскольку флаг взведен, прерывание щелкнет незамедлительно еще раз, данные будут записаны в освободившееся место. Это одно из возможных решений, которое я никому не навязываю. У меня так работают многие каналы. На результаты жалоб нет.


Сообщение отредактировал KnightIgor - Jun 6 2017, 20:11
Go to the top of the page
 
+Quote Post
_lexa_
сообщение Jun 6 2017, 20:56
Сообщение #45


Участник
*

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



Цитата(jcxz @ Jun 6 2017, 08:20) *
Открываем мануал на 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."

судя по этому абзацу да по остальному в мануалах (применительно к cortex-m4) для синхронизации на LDREX/STREX достаточно одной единственной ячейки памяти, которую будут читать/писать LDREX/STREX, на весь исполняемый процессором код. А для STM32f4 даже настройки MPU не потребуется (кэша на RAM там нет)

Цитата(jcxz @ Jun 6 2017, 08:20) *
Влияние доступов от DMA и прочих bus-masters на exclusive monitor - также представляется крайне сомнительным, так как:

Я так понимаю, AVI-crak просто провел эксперимент, в результате которого DMA сбросил тэг монитора, и здесь не стоит вопрос нужно ли это или не нужно. По поводу того, где это сказано, конечно не совсем про то, но в принципе сюда можно взглянуть:
ARMv7-M Architecture Reference Manual
A3.4.5 Load-Exclusive and Store-Exclusive usage restrictions
• 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.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 6 2017, 21:36
Сообщение #46


Гуру
******

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



Цитата(KnightIgor @ Jun 6 2017, 22:34) *
Рассмотрим пример. Сразу оговорюсь, что речь не о глобальном запрете прерывания, а о запрете периферийного. Но и Вы пишете об ISR вообще.

Передёргиваете. При чём тут маскирование определённого прерывания? Это вполне штатная ситуация, сам так часто делаю. Разговор был о глобальном флаге запрета всех прерываний.
Если даже это вдруг по каким-то причинам нужно, то это не является штатным случаем. Но для таких особых случаев и код особый. В остальных 99.9% - те критические секции что я описал вполне работоспособны.
Да вообще - какой смысл спорить то? О чём?? Откройте исходники какой-нить ОС - посмотрите как эти критические секции реализованы. И объясняйте их создателем что они дураки, а Вы один умный.
Откройте любые примеры идущие с компилятором - посмотрите.
Понятно что все вокруг дураки, один Вы умный.....

Цитата(_lexa_ @ Jun 6 2017, 22:56) *
для синхронизации на LDREX/STREX достаточно одной единственной ячейки памяти

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

Цитата(_lexa_ @ Jun 6 2017, 22:56) *
По поводу того, где это сказано, конечно не совсем про то, но в принципе сюда можно взглянуть:

Это не то что "не совсем то", а совсем не то. Там речь о "других CPU". Для других CPU - кто-ж спорит - это конечно нужно, если программа выполняется на нескольких ядрах.
Я писал про другие bus-masters типа DMA, Ethernet-контроллеров и прочего, которое не выполняет программы, задачи, не выполняет какой-то код, задачи которого не нужно синхронизировать с другими задачами.
Go to the top of the page
 
+Quote Post
Alechek
сообщение Jun 7 2017, 08:31
Сообщение #47


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

Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882



Цитата(jcxz @ Jun 6 2017, 13:20) *
Фантазии про некий регистр рассеиваются laughing.gif


Опять открываем мануалs

Цитата(ARM ® v7-M Architecture Reference Manual)
A3.4 Synchronization and semaphores
The model for the use of a Load-Exclusive/Store-Exclusive instruction pair, accessing memory address x is:
• The Load-Exclusive instruction always successfully reads a value from memory address x
• The corresponding Store-Exclusive instruction succeeds in writing back to memory address x only if no other
processor or process has performed a more recent store of address x
. The Store-Exclusive operation returns
a status bit that indicates whether the memory write succeeded.
A Load-Exclusive instruction tags a small block of memory for exclusive access. The size of the tagged block is
IMPLEMENTATION DEFINED, see Tagging and the size of the tagged memory block on page A3-75. A Store-Exclusive
instruction to the same address clears the tag.

A3.4.3 Tagging and the size of the tagged memory block
As shown in Figure A3-6 on page A3-71 and Figure A3-7 on page A3-74, when a LDREX instruction is executed, the
resulting tag address ignores the least significant bits of the memory address:
Tagged_address == Memory_address[31:a]
The value of a in this assignment is IMPLEMENTATION DEFINED, between a minimum value of 2 and a maximum
value of 11. For example, in an implementation where a = 4, a successful LDREX of address 0x000341B4 gives a tag
value of bits[31:4] of the address, giving 0x000341B. This means that the four words of memory from 0x000341B0 to
0x000341BF are tagged for exclusive access. Subsequently, a valid STREX to any address in this block will remove the
tag.A3 ARM Architecture Memory Model
A3.4 Synchronization and semaphores
A3-76 Copyright © 2006-2008, 2010, 2014 ARM. All rights reserved. ARM DDI 0403E.b
Non-Confidential ID120114
The size of the tagged memory block is called the Exclusives reservation granule. The Exclusives reservation
granule is IMPLEMENTATION DEFINED between:
• One word, in an implementation with a == 2.
• 512 words, in an implementation with a == 11.
Note
For the local monitor, one of the IMPLEMENTATION DEFINED options is for the monitor to treat any access as
matching the address of the previous Load-Exclusive access. In such an implementation, the Exclusives reservation
granule is the entire memory address range.


Цитата(ARM® Cortex®‑M4 Processor Technical Reference Manual )
3.6 Exclusive monitor

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.



Цитата(Cortex-M3 Technical Reference Manual (r2p0))
3.6. Exclusive monitor
The Cortex-M3 processor implements a local exclusive monitor. For more information about semaphores and the local exclusive monitor see the ARMv7M ARM Architecture Reference Manual.


Так что вырисовывается вот что:
- вся память поделена на регионы размером [Exclusives reservation granule]
- есть N регистров эксклюзивного доступа к памяти, где N от 1 до RAM_SIZE/[Exclusives reservation granule]
- сбрасывается эксклюзивный доступ РЕГИОНА при ЛЮБОЙ явной записи в этот РЕГИОН
- для Cortex-M3 размер [Exclusives reservation granule] явно не определен и, по всей видимости, определяется производителем.
- для Cortex-M4 размер [Exclusives reservation granule] равен всей памяти.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 7 2017, 08:56
Сообщение #48


Гуру
******

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



Цитата(Alechek @ Jun 7 2017, 10:31) *
Опять открываем мануалs

Не тот мануал открываете. Этот мануал - на архитектуру в целом (по которой построены разные ядра), а я Вам приводил на конкретное ядро, соответствующее топику - читайте внимательнее.
И даже в выделенном Вами фрагменте архитектурного мануала уже указано "IMPLEMENTATION DEFINED", а в мануале на ядро M4, основанное на этой архитектуре это NOT IMPLEMENTED - вполне законно.

Цитата(Alechek @ Jun 7 2017, 10:31) *
- есть N регистров эксклюзивного доступа к памяти, где N от 1 до RAM_SIZE/[Exclusives reservation granule]
...

Ещё раз, для самых непонятливых: откройте мануал на конкретное ядро, то есть - "ARM Cortex-M4 Processor Technical Reference Manual" и оставьте свои пустые фантазии.

Цитата(Alechek @ Jun 7 2017, 10:31) *
- вся память поделена на регионы размером [Exclusives reservation granule]

Эта фраза из TRM: "This means that the implemented exclusives reservation granule is the entire memory address range." - означает что "есть только одна гранула, размером со всю память".

А эта фраза TRM:
"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."
Означает что инструкция LDREX относится к предыдущей инструкции STREX с любым адресом (т.е. - любой адрес является "matching the address") вне зависимости от адреса.
Go to the top of the page
 
+Quote Post
Alechek
сообщение Jun 7 2017, 09:18
Сообщение #49


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

Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882



Цитата
Не тот мануал открываете

Ну почему же не тот? Я все открыл, смотрите выше.
И мануалы на М4 и на М3 там тоже есть.
Выводы подправил.

А вот Вы вводите людей в заблуждение:
Цитата(jcxz @ Jun 5 2017, 12:49) *
Если между LDREX и STREX произошло прерывание или был выполнен другой эксклюзивный доступ, до будет нарушение эксклюзивности.
Ну и где у вас между LDREX и STREX нарушение эксклюзивности?


Про условие эксклюзивной записи для нарушения эксклюзивности - нет такого!
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 7 2017, 09:29
Сообщение #50


Гуру
******

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



Цитата(Alechek @ Jun 7 2017, 11:18) *
Про условие эксклюзивной записи для нарушения эксклюзивности - нет такого!

В смысле нет?
Если у Вас есть пара LDREX_1/STREX_1 и Вы внутри этой пары, между LDREX_1 и STREX_1 поставите другую STREX_2, то STREX_1 вернёт статус - нарушение эксклюзивности.
Потому что триггер эксклюзивного доступа был сброшен STREX_2.
Go to the top of the page
 
+Quote Post
Alechek
сообщение Jun 7 2017, 10:21
Сообщение #51


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

Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882



Цитата(jcxz @ Jun 7 2017, 14:29) *
В смысле нет?
Если у Вас есть пара LDREX_1/STREX_1 и Вы внутри этой пары, между LDREX_1 и STREX_1 поставите другую STREX_2, то STREX_1 вернёт статус - нарушение эксклюзивности.
Потому что триггер эксклюзивного доступа был сброшен STREX_2.

В смысле, если между LDREX_1/STREX_1 сделать простой STR (в этот регион), то будет нарушение эксклюзивности.
Go to the top of the page
 
+Quote Post
scifi
сообщение Jun 7 2017, 10:27
Сообщение #52


Гуру
******

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



Цитата(Alechek @ Jun 7 2017, 13:21) *
В смысле, если между LDREX_1/STREX_1 сделать простой STR (в этот регион), то будет нарушение эксклюзивности.

Это называется "глюк в софте". Систему можно и проще поломать - просто забейте весь стек мусором biggrin.gif
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 7 2017, 11:23
Сообщение #53


Гуру
******

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



Цитата(Alechek @ Jun 7 2017, 12:21) *
В смысле, если между LDREX_1/STREX_1 сделать простой STR (в этот регион), то будет нарушение эксклюзивности.

А зачем так делать??
Go to the top of the page
 
+Quote Post
LightElf
сообщение Jun 7 2017, 11:52
Сообщение #54


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

Группа: Участник
Сообщений: 180
Регистрация: 5-04-09
Пользователь №: 47 205



QUOTE (jcxz @ Jun 7 2017, 00:36) *
Я писал про другие bus-masters типа DMA, Ethernet-контроллеров и прочего, которое не выполняет программы, задачи, не выполняет какой-то код, задачи которого не нужно синхронизировать с другими задачами.

На жирных камнях с многоуровневыми кэшами - вполне может проверяться активность других bus-masters. На Cortex-M точно нет.
Вообще про LDREX/STREX лучше читать не у ARM, а у авторов - Hitachi SH. А правильное применение есть в сорцах Keil RTX

QUOTE (Alechek @ Jun 7 2017, 13:21) *
В смысле, если между LDREX_1/STREX_1 сделать простой STR (в этот регион), то будет нарушение эксклюзивности.

Нет, не будет.
Go to the top of the page
 
+Quote Post
Alechek
сообщение Jun 7 2017, 12:22
Сообщение #55


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

Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882



Цитата(scifi @ Jun 7 2017, 15:27) *
Это называется "глюк в софте". Систему можно и проще поломать - просто забейте весь стек мусором biggrin.gif

Цитата(jcxz @ Jun 7 2017, 16:23) *
А зачем так делать??

Господа, оставьте эти риторические вопросы. Здесь не обсуждается вопрос ЗАЧЕМ.
Нет ничего невозможного.
Arduino уже добрался до Cortex! Сделать вызов функции между LDREX/STREX - как раз плюнуть!

От неправильного применения может спасти только чтение правильной документации.

Цитата(LightElf @ Jun 7 2017, 16:52) *
Нет, не будет.


А поподробней? Практика или документация?
Пока что из того, что я привел, должно быть нарушение. Ошибка в ней или я что-то недочитал?
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 7 2017, 12:39
Сообщение #56


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

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



Цитата(LightElf @ Jun 7 2017, 14:52) *
А правильное применение есть в сорцах Keil RTX


Действительно - готовое решение. Спасибо за наводку )))

Причем в примере ниже два способа - через запрет /разрешения всех прерываний и через ldrex/strex.

..\Keil 5\ARM\Pack\ARM\CMSIS\5.0.0\CMSIS\RTOS\RTX\SRC\rt_MemBox.c:

CODE
/*--------------------------- rt_alloc_box ----------------------------------*/

void *rt_alloc_box (void *box_mem) {
/* Allocate a memory block and return start address. */
void **free;
#ifndef __USE_EXCLUSIVE_ACCESS
U32 irq_mask;

irq_mask = (U32)__disable_irq ();
free = ((P_BM) box_mem)->free;
if (free) {
((P_BM) box_mem)->free = *free;
}
if (irq_mask == 0U) { __enable_irq (); }
#else
do {
if ((free = (void **)__ldrex(&((P_BM) box_mem)->free)) == 0U) {
__clrex();
break;
}
} while (__strex((U32)*free, &((P_BM) box_mem)->free));
#endif
return (free);
}


и тут: rt_HAL_CM.h

Код
/* Functions */
#ifdef __USE_EXCLUSIVE_ACCESS
#define rt_inc(p)     while(__strex((__ldrex(p)+1U),p))
#define rt_dec(p)     while(__strex((__ldrex(p)-1U),p))
#else
#define rt_inc(p)     __disable_irq();(*p)++;__enable_irq();
#define rt_dec(p)     __disable_irq();(*p)--;__enable_irq();
#endif



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


Гуру
******

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



Цитата(Alechek @ Jun 7 2017, 15:22) *
Сделать вызов функции между LDREX/STREX - как раз плюнуть!

И эта функция называется SelfDestruct(!Now) biggrin.gif
Хватит вы думывать небылицы wacko.gif
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 7 2017, 13:13
Сообщение #58


Гуру
******

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



Цитата(Forger @ Jun 7 2017, 14:39) *
Причем в примере ниже два способа - через запрет /разрешения всех прерываний и через ldrex/strex.
#define rt_inc(p) __disable_irq();(*p)++;__enable_irq();
#define rt_dec(p) __disable_irq();(*p)--;__enable_irq();

В uCOS сделано лучше:
typedef unsigned int OS_CPU_SR;
#define OS_CPU_SR_ALLOCATE() OS_CPU_SR cpu_sr //Allocate storage for CPU status register
#define OS_ENTER_CRITICAL() {cpu_sr = __get_PRIMASK(); __disable_interrupt();}
#define OS_EXIT_CRITICAL() {__set_PRIMASK(cpu_sr);}

чтобы, если перед OS_ENTER_CRITICAL() были запрещены, то после OS_EXIT_CRITICAL() так и остались.
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 7 2017, 13:27
Сообщение #59


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

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



Цитата(jcxz @ Jun 7 2017, 16:13) *
чтобы, если перед OS_ENTER_CRITICAL() были запрещены, то после OS_EXIT_CRITICAL() так и остались.

Оно так и сделано в приведенном выше примере. см. void *rt_alloc_box (void *box_mem) в файле rt_MemBox.c

Но мне гораздо нравится больше как это сделано во freertos, там юзается basepri (кроме CM0), т. е. запрещаются не все прерывания.
Точнее, никогда не запрещаются прерывания, обладающие приоритетом выше, чем заданный в настройках порта freertos - configMAX_SYSCALL_INTERRUPT_PRIORITY
С одним ограничением - в таких lockfree прерываниях категорически нельзя использовать сервисы rtos.
Чтобы это все правильно работало, NVIC нужно настраивать исключительно на полностью вытесняющие прерывания:

Код
NVIC_SetPriorityGrouping(0); // 4 bits for pre-emption priority, 0 bits for subpriority



CODE

#define portDISABLE_INTERRUPTS() vPortRaiseBASEPRI()
#define portENABLE_INTERRUPTS() vPortSetBASEPRI( 0 )
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()

.....

static portFORCE_INLINE void vPortRaiseBASEPRI( void )
{
uint32_t ulNewBASEPRI = configMAX_SYSCALL_INTERRUPT_PRIORITY;

__asm
{
/* Set BASEPRI to the max syscall priority to effect a critical
section. */
msr basepri, ulNewBASEPRI
dsb
isb
}
}
/*-----------------------------------------------------------*/

static portFORCE_INLINE void vPortClearBASEPRIFromISR( void )
{
__asm
{
/* Set BASEPRI to 0 so no interrupts are masked. This function is only
used to lower the mask in an interrupt, so memory barriers are not
used. */
msr basepri, #0
}
}


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


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

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



Цитата(Alechek @ Jun 7 2017, 17:22) *
А поподробней? Практика или документация?
Пока что из того, что я привел, должно быть нарушение. Ошибка в ней или я что-то недочитал?

Практика. Выше я уже приводил ссылку на предыдущее обсуждение LDREX/STREX. Там тесты разных вариантов.

Видимо, в документации под словом "more recent store of address x" подразумевается всё же STREX.


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


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

Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882



AHTOXA, спасибо, ознакомился.
Но, опять противоречивые результаты:
AVI-crak говорит, что флаг сбрасывает любая запись по адресу, хоть DMA.
ArtDenis в своих тестах показывает, что даже явная запись не сбрасывает.
AlexandrY утверждает, что у него явная запись сбрасывает флаг, а неявная (PUSH) - не меняет состояние.

Походу, собака порылась в
Цитата(ARM ® v7-M Architecture Reference Manual)
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 памяти:
Цитата(ARM ® v7-M Architecture Reference Manual)
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), при ЯВНОЙ записи могут сбросится только мониторы других ядер. Но по факту может быть что угодно в зависимости от конкретной реализации. Извращения проверять обязательно!
Цитата(ARM ® v7-M Architecture Reference Manual)
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.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 8 2017, 06:17
Сообщение #62


Гуру
******

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



Цитата(Alechek @ Jun 8 2017, 07:01) *
- LDREX/STREX применять только в паре, они для этого сделаны. Все остальное - от лукавого.

И правильно! Через DMA и пр. - ЗАЧЕМ???
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 8 2017, 06:21
Сообщение #63


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

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



Цитата(Alechek @ Jun 8 2017, 10:01) *
- LDREX/STREX применять только в паре, они для этого сделаны. Все остальное - от лукавого. Может сработать, а может и нет, зависит от конкретной реализации ядра

Именно. Различия в результатах тестов вызваны, скорее всего, различиями в реализации. (Ну или кто-то накосячил в тестахsm.gif)
Способ использования от этого не меняется - только в паре.
Добавьте в ваш список выводов, что монитор может срабатывать на любое изменение уровня прерываний (вход в прерывание или выход из него).

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


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


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

Группа: Свой
Сообщений: 1 241
Регистрация: 15-11-05
Из: Челябинск
Пользователь №: 10 882



Цитата(jcxz @ Jun 8 2017, 11:17) *
И правильно! Через DMA и пр. - ЗАЧЕМ???

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

Цитата(AHTOXA @ Jun 8 2017, 11:21) *
Добавьте в ваш список выводов, что монитор может срабатывать на любое изменение уровня прерываний

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

Цитата(AHTOXA @ Jun 8 2017, 11:21) *
ЗЫ. Хотя насчёт DMA - я лично не верю. В этом случае при непрерывно идущих быстрых транзакциях DMA можно наглухо зависнуть в LDREX/STREX.

Мне тоже идея с DMA не очень нравится.
Вроде как не обязательно Store от ядра должно исходить.... В одном месте так написано, в другом - по другому...
Вобщем, все на откуп реализации:
Прикрепленное изображение
Прикрепленное изображение

Опыты, только опыты... Ни в одной докуметации на MCU не видел таких тонкостей.
Go to the top of the page
 
+Quote Post
AVI-crak
сообщение Jun 8 2017, 13:21
Сообщение #65


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

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



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

И наверное главное, давайте указывать явно - какой чип в тесте на данный момент.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 8 2017, 13:39
Сообщение #66


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

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



Цитата(Alechek @ Jun 8 2017, 16:54) *
Вобщем, все на откуп реализации:

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

Цитата(Alechek @ Jun 8 2017, 16:54) *
Опыты, только опыты... Ни в одной докуметации на MCU не видел таких тонкостей.


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


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


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

Группа: Участник
Сообщений: 180
Регистрация: 5-04-09
Пользователь №: 47 205



QUOTE (AHTOXA @ Jun 8 2017, 09:21) *
Именно. Различия в результатах тестов вызваны, скорее всего, различиями в реализации. (Ну или кто-то накосячил в тестахsm.gif)
Способ использования от этого не меняется - только в паре.
Добавьте в ваш список выводов, что монитор может срабатывать на любое изменение уровня прерываний (вход в прерывание или выход из него).

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

Есть архитектура, есть реализация.
На Cortex-M, которые по определению одноядерные, монитор как таковой отсутствует. Есть просто один-единственный триггер. LDREX его взводит, STREX проверяет что установлен, выполняет запись и сбрасывает. Любое исключение сбрасывает бит. Принудительно можно сбросить через CLREX.
На на навороченных многоядерных камнях с MMU, многоуровневыми кэшами, множеством bus-master устройств реализация может быть совсем другой.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Jun 8 2017, 14:52
Сообщение #68


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

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



Цитата(LightElf @ Jun 8 2017, 18:44) *
Есть архитектура, есть реализация.
На Cortex-M, которые по определению одноядерные, монитор как таковой отсутствует. Есть просто один-единственный триггер. LDREX его взводит, STREX проверяет что установлен, выполняет запись и сбрасывает. Любое исключение сбрасывает бит. Принудительно можно сбросить через CLREX.

Не вижу в вашем высказывании противоречия с моим. (Или вы не возражали, а дополняли?)
И на Cortex-M есть нюансы. Где-то обычная запись сбрасывает монитор, а где-то -- нет. Где-то DMA сбрасывает монитор, а где-то -- нет.


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


Гуру
******

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



Цитата(AVI-crak @ Jun 8 2017, 15:21) *
Неявная запись (PUSH) - является отложенным событием (как и любая запись кучи регистров), код выполняется параллельно, сбросить физику с подтверждением не получится, но можно немного подождать

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

Цитата(AVI-crak @ Jun 8 2017, 15:21) *
в пустом цикле или сбросить конвейер.

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

Цитата(AVI-crak @ Jun 8 2017, 15:21) *
И наверное главное, давайте указывать явно - какой чип в тесте на данный момент.

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

Цитата(LightElf @ Jun 8 2017, 15:44) *
На Cortex-M, которые по определению одноядерные

Вы это расскажите NXP с их линейкой LPC43xx. Про свои определения. cool.gif
Или Ваш мир Cortex-M ограничен STM32?
Курица - не птица, Cortex-M - не STM! Рифма одна-ко. Надо в подпись внести © biggrin.gif
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 9 2017, 07:50
Сообщение #70


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

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



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

А, чтобы разделить переключатель контекста rtos и юзерские вызовы этого самого pendSV, скажем, в R0 кладем адрес функции, а в остальные регистры ее параметры, а уже внутри pendSV все это разбираем.
Приоритет pendSV самый низкий (ниже лишь systick).
Тогда другой вызов pendSV прервать его не сможет, а лишь поставить в очередь. Т.е. обеспечивается атомарность действий как в прерываниях, так и в основном коде.
Вижу одно ограничение - передавать в такие функции указатели нежелательно, а можно лишь готовые данные (прямо в регистры R1...), т.е. ограничен объем передаваемых данных.
В противном случае нет никакой гарантии, что к моменту вызова соотв. функции (внутри pendSV) данные по указателям будут актуальны.

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


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


Гуру
******

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



Цитата(Forger @ Jun 9 2017, 09:50) *
зы. Предположительно вангую грабли со вложенными вызовами (вытесняющие прерывания), где оба обработчика вызывают pendSV...

PendSV не "вызывают", а лишь возбуждают запрос на него. В том числе и в ISR-ах, где вход в PendSV будет отложен до завершения всех других ISR, а из фонового процесса - вход в PendSV будет сразу, подобно синхронному SVC.
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 9 2017, 10:58
Сообщение #72


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

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



Цитата(jcxz @ Jun 9 2017, 13:33) *
PendSV не "вызывают" ...
Да, это-то понятно, это все - придирки к словам, а речь о другом:
как сделать так, чтобы pendSV могли вызывать взводить разные обработчики, особенно вложенные друг в друга, но так, чтобы в стеке сформировалась очередь данных, которые позволят этот pendSV обработать несколько раз подряд и не потерять ни одного запроса и не разрушить стек?
Понятно, что pendSV не для этого был задуман, но тем не менее ))

Размышляя вслух дальше - выполняемый в данный момент pendSV может прервать другое более приоритетное прерывание и опять накидать в стек новых данных перед взводом pendSV,
Или использовать внутри pendSV вызов соотв. SVC, который имеет приоритет выше pendSV...
Заумно как-то выходит. Но возможно ли осуществить что-то подобное?
Цель - избежать критических секций с запретом прерываний и "капризного" LDREX/STREX.


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


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(Forger @ Jun 9 2017, 13:58) *
как сделать так, чтобы pendSV могли вызывать взводить разные обработчики, особенно вложенные друг в друга, но так, чтобы в стеке сформировалась очередь данных, которые позволят этот pendSV обработать несколько раз подряд и не потерять ни одного запроса и не разрушить стек?

Очередь данных в стеке не формируется - формируйте ее отдельно, а потом обрабатывайте в PendSV. Но для данной задачи это неэффективно и не имеет смысла - есть LDREX/STREX, если его не хватает, то есть запрет части или всех прерываний.
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 9 2017, 13:20
Сообщение #74


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

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



Цитата(Шаманъ @ Jun 9 2017, 16:02) *
Очередь данных в стеке не формируется - формируйте ее отдельно, а потом обрабатывайте в PendSV.
А все равно грабли - процесс формирования очереди должен быть защищен критической секцией, масло масляное (((

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

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

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

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





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


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(Forger @ Jun 9 2017, 16:20) *
хочется ведь гипотетического универсального решения

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

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

Интересно зачем? Если это что-то типа кольцевого буфера приделанного к UART, то один указатель изменяется только в задаче, а второй только в прерывании. Пересечения между ними не происходит. Семафор это головная боль ОС. Вот и все. У меня сделано похожим образом.
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 9 2017, 14:30
Сообщение #76


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

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



Цитата(Шаманъ @ Jun 9 2017, 17:14) *
Интересно зачем? Если это что-то типа кольцевого буфера приделанного к UART, то один указатель изменяется только в задаче, а второй только в прерывании. Пересечения между ними не происходит.

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

Именно это я и описал выше.
У меня очередь сделана в виде шаблона, всего один параметр - тип данных.
При создании экземпляра очереди ей передается ссылка на класс Interrupt, в котором есть два обязательным метода disable и enable.
Для каждой очереди он может быть свой, поэтому запрещаются лишь те прерывания, которые конфликтуют с конкретным экземпляром очереди.

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


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


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

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



Защищённый режим: стек для потоков psp, стек для прерываний msp.
Поток не имеет прямого доступа к части системных регистров.
Приоритет SVC - 0.
Пользовательские прерывания 1~14.
Системный таймер, и таймер реального времени =15.
Любой поток и прерывание может вызвать SVC без разрушения стека. Системный таймер и таймер реального может прервать любое прерывание, все изменения при этом будут скидываться стек прерываний, и восстанавливаться до первоначального вида совершенно автоматически.
Кукла для всех прерываний не требуется!!!

Проблема половины бесплатных ос - в наследии от пиков да авр, где защищённый режим просто не существовал. Переписывать всю ось нет смысла - вот и продолжают пользоваться кактусом.

Go to the top of the page
 
+Quote Post
Шаманъ
сообщение Jun 9 2017, 15:40
Сообщение #78


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(Forger @ Jun 9 2017, 17:30) *
При чем тут это?
Я лишь привел пример с осью, как наиболее универсальный.
Но кто не пользуется осью, могут просто поллить некий флажок в основном коде, а в прерываниях его взводить или инкрементировать.
Способ оповещения основного кода в данном случае не имеет никакого значения. Отклоняемся от темы )))

Это как раз причина по которой у меня с ОС не происходит, а с "неким флажком" происходит. Поясняю:

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

Теперь про голову - данные из UART выгребаем в прерывании, в этом же прерывании увеличиваем счетчик семафора и добавляем в очередь. Чтобы избежать переполнения очереди достаточно проверить счетчик семафора. Вот собственно и все. Счетчик семафора это проблема ОС, остальное (очередь и указатели на голову/хвост) в полной безопасности.

Если интересно, как сделана у меня в ОС работа с семафорами, то через те же LDREX/STREX sm.gif Правда это если не касаться вопросов переключения задач и системных вызовов, но то уже точно другая тема.
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 9 2017, 16:27
Сообщение #79


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

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



Цитата(Шаманъ @ Jun 9 2017, 18:40) *
Это как раз причина по которой у меня с ОС не происходит, а с "неким флажком" происходит. Поясняю:

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


Цитата(AVI-crak @ Jun 9 2017, 17:38) *
Приоритет SVC - 0.
Пользовательские прерывания 1~14.
Системный таймер, и таймер реального времени =15.

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

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


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


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(Forger @ Jun 9 2017, 19:27) *
Я говорю про совсем другое - манипулирование индексами головы, хвоста и изменяемых данных которые должны меняться в едином непрерывном блоке кода.
Если обработчик прерываний разорвет эту цепочку в самом неподходящем месте, то рано или поздно произойдет HF.

От же ж...ну как Вам еще объяснить. Читайте внимательно и думайте:
1. Указатель на голову (куда добавляются данные) он используется только в прерывании которое добавляет данные, только там, и больше нигде.
2. Указатель на хвост (откуда вычитываются данные) он используется только в задаче которая читает данные, только там, и больше нигде.

Синхронизация делается семафором, как и защита от переполнения/недополнения. К семафору есть доступ и у задачи, и у прерывания, но он делается через ОС.

Теперь понятно? Если нет, то перечитайте пожалуйста еще раз, ну или несколько раз - не знаю как объяснить иначе...
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 9 2017, 17:23
Сообщение #81


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

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



Цитата(Шаманъ @ Jun 9 2017, 20:08) *
От же ж...ну как Вам еще объяснить. Читайте внимательно и думайте:

Я про Фому, а он - про Ерему ...

Ясен пень, что голова и хвост изменяются в разным местах - один в фоне задач, другой - в перрывании, но !
Чтобы проверить переполнение/исчерпание, нужно контроллировать в непрерывном куске кода ОБА указателя/индекса.
Это можно делать только там, где производите изменение этих самых указателей/индексов - в прерывании и в фоне задач.
В прерывании это не проблема - защищать ничего не нужно, достаточно лишь не класть в буфер новые данные и кинуть соотв. сообщение/исключение.
А в фоне задачи нужно защищать обращение к ОБОИМ указателям в некой критической секции, иначе невозможно контроллировать подобные аварийные события.
Если этого не делать, то буфер может быть переполнен/исчерпан так, что об этом невозможно будет узнать.

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

Цитата
Синхронизация делается семафором...

Точно, я про Фому, а он - про Ерему )))


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


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(Forger @ Jun 9 2017, 20:23) *
Чтобы проверить переполнение/исчерпание, нужно контроллировать в непрерывном куске кода ОБА указателя/индекса.

Нет. Достаточно проверить состояние семафора.

Цитата
А в фоне задачи нужно защищать обращение к ОБОИМ указателям в некой критической секции, иначе невозможно контроллировать подобные аварийные события.
Если этого не делать, то буфер может быть переполнен/исчерпан так, что об этом невозможно будет узнать.

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

Про прерывание Вы и сами написали. Так кто там про Фому laughing.gif

Цитата
Также реализуется обратная ситуация - задача кладет данные в буфер, взводит нужное прерывание и уже в соотв. обработчике буфер выгребается и отправляется во вне.
Чтобы положить данные в буфер в фоне задачи, нужно обращаться в непрерывном куске кода к ОБОИМ указателям. Поэтому тут нужна критическая секция или что-то подобное.

Да не нужно - достаточно семафора.

P.S. Может быть Вы не так понимаете что такое семафор. У меня это объект синхронизации задач, который может принимать значения от 0 до некоторого MAX. Счетчик семафора показывает доступность ресурса (в данном случае кол-во данных в очереди). Задача может запросить конкретное кол-во данных или диапазон (от и до) - если нужное кол-во доступно, то задача получит запрошенное кол-во данных, если нет, то будет приостановлена, пока не будет доступно запрошенное кол-во данных.
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 9 2017, 17:48
Сообщение #83


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

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



Цитата(Шаманъ @ Jun 9 2017, 20:40) *
Если напрячься и таки подумать, то в задаче буфер переполнен не модет быть вообще, ибо она данные только читает. ...
Не, это - уже бесполезный спор.


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


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(Forger @ Jun 9 2017, 20:48) *
Не, это - уже бесполезный спор.

Конечно, ибо то, о чем я пишу работает sm.gif

ОК поставим вопрос по-другому, каким образом может быть переполнен буфер в задаче, которая из него только читает?
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 9 2017, 18:04
Сообщение #85


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

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



Цитата(Шаманъ @ Jun 9 2017, 20:56) *
Конечно, ибо то, о чем я пишу работает sm.gif

И самолеты летают. Но иногда, увы, падают sad.gif

Цитата
ОК поставим вопрос по-другому, каким образом может быть переполнен буфер в задаче, которая из него только читает?

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


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

Я делал это несколько иначе, использовал счетчик свободного места, вообще не сравнивая указатели. Это получается несколько быстрее, но отъедает немного места в памяти.
Обращение к этому счетчику и изменение соотв. указателей, должно быть непрерывным. Иначе - HF


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


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(Forger @ Jun 9 2017, 21:04) *
И самолеты летают. Но иногда, увы, падают sad.gif

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

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

Гениально. Для меня чтение из очереди это всегда было как получение данных, так и коррекция указателя.

Цитата
При заполнении буфера (в прерывании) нужно сравнивать ОБА указателя.
Если это прерывание возникнет между чтением данных в задаче и изменением соотв. указателя, то будет беда.

И в чем беда? Прочитали данные, потом произошло прерывание (в нем сравнили указатели и изменили указатель головы, кстати, в некоторых случаях можно указатели и вообще не сравнивать - достаточно кол-ва данных в очереди = значения семафора), потом (когда возвратились в задачу) изменили указатель хвоста - что мы имеем - в прерывании размер очереди был на 1 ячейку меньше, все. Никаких проблем нет. Сами же выше написали про это, а теперь "надумали" проблему там, где ее нет.

Цитата
При обратной ситуации - задача набивает буфер для передачи через прерывание

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

Цитата
Я делал это несколько иначе, использовал счетчик свободного места, вообще не сравнивая указатели. Это получается несколько быстрее, но отъедает немного места в памяти.
Обращение к этому счетчику и изменение соотв. указателей, должно быть непрерывным. Иначе - HF

Свободное место или занятое это одно и то же (свободное = размер - занятое sm.gif), т.е. Вы говорите +- о том же, что и я писал выше и сейчас. Какой HF? Отчего? Выше я написал реальный пример, объясните где там будет HF? Даже если накосячить, то все, что может быть это потеря данных в очереди из-за переполнения.

Сообщение отредактировал Шаманъ - Jun 9 2017, 18:58
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 9 2017, 19:18
Сообщение #87


Гуру
******

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



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

И в фоновом процессе это тоже не нужно. Так как измениться в этот момент может ТОЛЬКО ОДИН указатель.
Подумайте ещё раз.

Цитата(Forger @ Jun 9 2017, 19:23) *
Если этого не делать, то буфер может быть переполнен/исчерпан так, что об этом невозможно будет узнать.

Вы похоже просто не понимаете как работают подобные кольцевые буфера... laughing.gif
Инфа для размышления:
Кольцевые буфера, построенные подобным образом вполне можно использовать даже в тех случаях, когда критические секции в принципе невозможны, например - кольцевой буфер обмена между двумя ядрами/процессорами.

Цитата(Forger @ Jun 9 2017, 19:48) *
Не, это - уже бесполезный спор.

Конечно бесполезный, если Вы не хотите понимать очевидных вещей. laughing.gif
Шаманъ Вам дело говорит.
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 9 2017, 19:18
Сообщение #88


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

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



Цитата(jcxz @ Jun 9 2017, 22:12) *
И в фоновом процессе это тоже не нужно. Так как измениться в этот момент может ТОЛЬКО ОДИН указатель.

Могут изменится оба, если в месте сравнения указателей и вычисления свободного/занятого места возникнет соотв. прерывание, которое изменит другой указатель.
Если в этот момент мы начали сравнивать два указателя (или читать некий счетчик свободного/занятого места), то к моменту сравнения он будет неактуальным - ведь в прерывании выше он уже изменился.

Если переполнение/исчерпание очереди не имеет значения для конкретного проекта, вообще не контролируется, то, конечно, можно забить на все эти критические участки кода.


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


Гуру
******

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



Цитата(Forger @ Jun 9 2017, 20:04) *
Я делал это несколько иначе, использовал счетчик свободного места, вообще не сравнивая указатели. Это получается несколько быстрее, но отъедает немного места в памяти.
Обращение к этому счетчику и изменение соотв. указателей, должно быть непрерывным. Иначе - HF

Вот как раз со счётчиком - это плохая реализация, так как обязательно требует критической секции.
Реализация кольцевого буфера на двух указателях (один - чтения, другой - записи) для своей работы не требует критических секций при условии, что есть только один процесс/ядро- писатель и только один процесс/ядро- читатель. И это справедливо только для этих процессов. Т.е. - не требуется ни для чего - ни для вычисления свободного места ни для вычисления уровня заполнения и т.п.
Если состояние кольца читается 3-ей стороной (процессом/ядром отличным от читателя и писателя), то для этого критическая секция нужна.
А в читателе и писателе - нет. Так как каждый из них модифицирует только один указатель, а второй указатель использует только на чтение.

Цитата(Forger @ Jun 9 2017, 21:18) *
Если в этот момент мы начали сравнивать два указателя (или читать некий счетчик свободного/занятого места), то к моменту сравнения он будет неактуальным - ведь в прерывании выше он уже изменился.

Ну и что что станет неактуальным?
Допустим пишущий процесс считал указатель чтения и, пока он его анализировал, произошло прерывание чтения, которое убавило данных из буфера. Ну и что? От этого работа кольца не разрушится. Просто пишущий процесс в этот момент будет думать что данных в кольце больше чем уже есть. Ну и что? Это не приведёт ни к каким сбоям. Вот если-б он думал что данных меньше чем там есть - вот это бы привело к разрушению работы. Но это невозможно по алгоритму.
Go to the top of the page
 
+Quote Post
Forger
сообщение Jun 9 2017, 19:39
Сообщение #90


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

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



Цитата(jcxz @ Jun 9 2017, 22:31) *
Вот как раз со счётчиком - это плохая реализация, так как обязательно требует критической секции.

Счетчик нужен для анализа переполнения/исчерпания очереди.
Если подобные события не представляют угрозы конкретному коду, то и счетчик не нужен.
И критические секции не нужны. Я с этим не спорю.
Я же говорю про код, где нужно контролировать такие события, нужно реагировать на такие вещи и предпринимать конкретные действия.
Особенно, если устройство всегда включено и работает далеко от пользователя/обслуги.
В этом случае контроль вынуждает защищать подобные куски кода.
Самое простое - критическими секциями.


--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
Go to the top of the page
 
+Quote Post
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

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

 


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


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