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

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

|
Всем доброе время суток! IDE - IAR+плагин IAR для eclipse+eclipse. Решил проверить, как работает синхронизация с использованием __LDREX/__STREX. Пишем следующий код CODE typedef struct { ... volatile unsigned long sync; //переменная для синхонизации доступа к данному элементу } burst_measur;
burst_measur cur_mes;
void mpu_cfg_test() { //настраиваем область внутренней RAM, как разделяемую __DMB(); SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk; MPU->CTRL = 0U;
MPU->RNR = 0UL; MPU->RBAR = 0x20000000UL; MPU->RASR = (0x10UL << MPU_RASR_SIZE_Pos) | MPU_RASR_C_Msk | MPU_RASR_S_Msk | (0x3 << MPU_RASR_AP_Pos) | MPU_RASR_ENABLE_Msk;
MPU->CTRL = MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk; SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk; __DSB(); __ISB();
//выполняем запрос эксклюзивного доступа к переменной cur_mes.sync DWORD sync=0; sync = __LDREX(&cur_mes.sync); __DMB(); soft_int_ini(); //настойка программного прерывания soft_int_on(); //вызов программного прерывания __WFI(); } в обработчике программного прерывания: CODE DWORD sync; do { sync = __LDREX(&cur_mes.sync); sync++; sync = __STREX(sync, &cur_mes.sync); } while (sync); Т.е. сначала выполняется __LDREX(&cur_mes.sync), потом происходит прерывание и выполняется __LDREX(&cur_mes.sync) + __STREX(sync, &cur_mes.sync). По всем документациям, как я их понял, __STREX(sync, &cur_mes.sync) должна возвратить "не ноль", однако возвращает "ноль". Помогите, пожалуйста, разобраться, что я делаю не правильно?
|
|
|
|
|
 |
Ответов
|
Jun 4 2017, 18:39
|
Участник

Группа: Участник
Сообщений: 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 вернет "не ноль". однако возвращается ноль. Где-то ошибся! Не понятно только где. Поясните вкратце, куда смотреть.
|
|
|
|
|
Jun 4 2017, 19:34
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(_lexa_ @ Jun 4 2017, 19:39)  Где-то ошибся! Не понятно только где. Поясните вкратце, куда смотреть. Каждый раз вспоминаю и снова забываю эти проклятые LDREX/STREX, но суть в том, что если между LDREX и последующим STREX "что-то пошло не так, Карл", а именно - возникло некоторое событие, прерывание, которое СТАВИТ ПОД УГРОЗУ целостность переменной-флага, то STREX вернет типа "ай-ай". То есть, даже если саму переменную-флаг никто и трогать не собирался где-то в недрах прерываний, но прерывание нарушило непрерывное исполнение между LDREX и STREX, то ресурс считается занятым. Поэтому у меня глубокое сомнение, можно ли строить код, как у ТС, - захватывать ресурс в основном коде и выяснять отношения в прерывании: в прерывании по определению ресурс будет занят. Если хотите организовать всякие мъютексы и прочие разделяемые флаги на системе bare bone с наличествующими прерываниями, гляньте на команду SVC. Могу даже код кинуть, если есть интерес.
|
|
|
|
|
Jun 4 2017, 20:14
|
Участник

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

|
Цитата(KnightIgor @ Jun 4 2017, 19:34)  ... Могу даже код кинуть, если есть интерес. Интерес есть. Кидайте.
|
|
|
|
|
Jun 4 2017, 21:14
|
Знающий
   
Группа: Участник
Сообщений: 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
|
|
|
|
|
Jun 5 2017, 08:17
|

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

|
Цитата(AHTOXA @ Jun 5 2017, 08:38)  А в чём выгода такого метода по сравнению с простым запретом/разрешением прерываний? Полагаю, что выгода в полным отсутствием этих самых запретов/разрешений. Дабы иметь возможность гарантировать стабильную скорость реакции на критичные высокоприоритетные прерывания. Причем, в независимости используется ось или нет. Сам поглядываю на подобные решения, но таких у меня проектов очень мало, поэтому пока вполне хватает "классического" запрет/разрешение прерываний. Хожу как "кот вокруг сметаны"  Цитата Я думаю, что по скорости это даже медленнее (тратится время на сохранение и восстановление контекста). Если производительность камня выбрана хотя бы с небольшим запасом (в случае применения оси загрузка cpu никогда не достигает допустимого предела), то это не имеет значения. Смысл svc - дать гарантию реакции на важные высокоприоритетные прерывания.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 5 2017, 08:49
|
Гуру
     
Группа: Свой
Сообщений: 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 ну-ну... учите матчасть Если это "мощное" прерывание попытается так сделать, то получит HardFault, а не SVC.
|
|
|
|
|
Jun 5 2017, 09:11
|

Профессионал
    
Группа: Свой
Сообщений: 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 понятна далеко не всем. Это как раз тот самый случай - изучить матчасть.
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 5 2017, 09:37
|
Гуру
     
Группа: Свой
Сообщений: 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 в проектах.
|
|
|
|
|
Jun 5 2017, 09:49
|

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

|
Цитата(jcxz @ Jun 5 2017, 12:37)  Вот именно.... Согласен, я поспешил с выводами  Выходит, что в более приоритетных прерываниях нельзя использовать svc, а можно лишь в задачах/потоках. Этого я не знал (( Я рассчитывал в реализациях программных очередей (queue) отказаться от критических секций (простое запрет/разрешение прерываний), но коли в прерываниях это создает трудности (скажем, прерывание от usart), то выходит, что svc ипользовать не получится. А жаль (( Или можно просто поднять приоритет svc до уровня чуть ниже важных прерываний (в которых запрещены вызовы серсвисов оси), тогда задача решится. Я прав?
--------------------
Кругозор некоторых людей - круг с нулевым радиусом. Они называют его "точкой зрения".
|
|
|
|
|
Jun 5 2017, 10:59
|
Гуру
     
Группа: Свой
Сообщений: 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 до уровня чуть ниже важных прерываний (в которых запрещены вызовы серсвисов оси), тогда задача решится. Я прав? Можно конечно, но ещё раз спрашиваю: зачем надевать трусы через голову?? Ведь если уж никак нельзя запрещать прерывания, то есть механизм LDREX/STREX, который именно для этого и создан. А SVC - даже из названия видно - это для вызова системных функций. Привилегированных. Можно конечно работу с очередями (или что там ещё) вынести на этот уровень, но зачем??? Это будет во много раз медленнее и громоздко чем LDREX/STREX. Цитата(_lexa_ @ Jun 5 2017, 12:17)  Если смотреть по коду, который я привел - первый запрос на эксклюзивный доступ здесь А что такое " запрос на эксклюзивный доступ"? Откуда Вы это взяли?? Нет такого понятия. Нет никаких запросов там. Эксклюзивный доступ read-modify-write - это пара инструкций LDREX/STREX работающих с некоей переменной. Эксклюзивно - это означает, что никто другой (другой процесс) не обращается к этой переменной между LDREX и STREX. А если это условие нарушается - это нарушение эксклюзивности. В Вашем случае есть одна только пара LDREX/STREX, её эксклюзивный доступ никто не нарушает. Похоже Вы совсем не поняли, что написано в мануале и для чего это вообще нужно. Перечитайте ещё раз.
|
|
|
|
|
Jun 5 2017, 13:26
|
Участник

Группа: Участник
Сообщений: 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)  Похоже Вы совсем не поняли, что написано в мануале и для чего это вообще нужно. Перечитайте ещё раз. В таком случае, если не сложно, приведите, пожалуйста, небольшой пример кода, когда происходит нарушение эксклюзивности.
|
|
|
|
|
Jun 5 2017, 14:21
|
Гуру
     
Группа: Свой
Сообщений: 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. Изучать ядро нужно по первоисточнику http://infocenter.arm.com/help/index.jsp, а не по переводам и толкованиям. А в первоисточнике нет никаких "requesting". Цитата(_lexa_ @ Jun 5 2017, 15:26)  ничего не изменится (на всякий случай я это даже проверил). Каким образом монитор эксклюзивного доступа должен увидеть, что использована именно пара LDREX/STREX Вот именно в таком случае - оно и сработает и обнаружит нарушение эксклюзивности. Команда LDREX взводит некий триггер в "1". STREX атомарно сбрасывает его и, если в в момент своего выполнения триггер стоял - выполняет операцию, если не стоял - не выполняет. И возвращает соотв. значение. Также любое прерывание сбрасывает этот триггер. А также команда CLREX тоже сбрасывает. Вот и всё. Всё просто.
|
|
|
|
|
Jun 5 2017, 17:37
|
Частый гость
 
Группа: Участник
Сообщений: 182
Регистрация: 16-10-15
Пользователь №: 88 894

|
Начали за упокой, кончили за здравие.
Как уже было сказано, LDREX выставляет атомарный флаг при использовании команды в потоке, конкретно на используемый адрес. Точнее конкретный адрес чтения выставляется на мониторе, и отслеживается аппаратными механизмами сразу на интерфейсе памяти. Атомарный флаг может сбросить любое прерывание, любое аппаратное чтение/запись по этому адресу (например DMA). Флаг не сбрасывается в момент применения команды LDREX в прерывании и перебивании его более высоким приоритетом. Отчего костыль для использования в прерывании содержит собственный сброс до и после. STREX выполняется, или не выполняется без использования программной проверки атомарного флага, этот механизм выполнен полностью аппаратно. STREX выдаёт флаг, видимый для программы - для проверки успешности операции.
Выполнение STREX в потоке - автоматически сбрасывает атомарный флаг, не важно какой результат успеха. Использование в прерывании STREX не гарантирует сброс, но успешно и корректно выставляет программный флаг для проверки операции. Мойте перед и зад - это есть костыль.
+Ещё один важный прикол - конвейер. Лучше перебздеть, и подтверждать полный сброс данных в память. +Ещё грабли - LDREX STREX могут применяться на той памяти, что имеет прямое подключение к ядру мк. Например в М7 часть памяти заведена через ускоритель, в результате применение LDREX STREX моментально вешает мк.
------------ SVC - безусловное прерывание. Отрабатывается без вытеснения из любой позиции. Перебить SVC - просто невозможно. SVC - это рыба для сервисов ОС, с небольшим количеством шаманства - превращается в очень удобную функцию. У меня на SVC полностью работает собственная ось.
|
|
|
|
|
Jun 5 2017, 21:35
|
Гуру
     
Группа: Свой
Сообщений: 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 было прерывание (или переключение контекста, которое тоже выполняется через прерывание), то значит - нет гарантии, что операция чтение-модификация-запись была эксклюзивной. Похоже Вы так и не поняли зачем нужен и как работает этот эксклюзивный доступ... Цитата(_lexa_ @ Jun 5 2017, 19:40)  Бесполезность LDREX/STREX для синхронизации косвенно подтверждается еще и тем, что в CMSIS-RTOS эти команды в мутексах и семафорах не используются. Они и не должны там использоваться если ОС должна быть мультиплатформенной. Они могут использоваться в портах ОС. Понятно - все дураки, и создатели ядра и создатели IAR-а например, да все кто поддерживает эти LDREX/STREX - не понимают они их бесполезность. Объясните им  Цитата(AVI-crak @ Jun 5 2017, 20:00)  Нет широкого распространения по другой причине - память должна подключаться к ядру без цепочек ускорителей. То-есть команды LDREX/STREX гарантированно выполняются на всех arm чипах, но не на всей используемой памяти. Эксклюзивный доступ нужен не к массивам памяти, а к отдельным переменным, коих в программе обычно мало. Достаточно вынести их в отдельный регион памяти и объявить его некешируемым (через MPU). Цитата(KnightIgor @ Jun 5 2017, 21:42)  Что будет, если после сохранения текущего статуса разрешения прерываний в выделеной переменной (оно было разрешено), но до исполнения самой инструкции запрета прерывания произойдет-таки прерывание, которое по какой-либо логике всей программы запретит прерывания? Как я понимаю, после выхода из критической секции прерывание будет-таки разрешено , т.к. будет восстановлено из переменной? Ну наверное. А что это за прерывание такое, которое внутри себя запрещает прерывания??? Аппаратное асинхронное? Т.е. - оно может вызваться в любой точке и в произвольный момент времени запретить прерывания? А зачем это нужно и как может такая программа вообще функционировать?
|
|
|
|
|
Jun 6 2017, 07:24
|
Частый гость
 
Группа: Участник
Сообщений: 182
Регистрация: 16-10-15
Пользователь №: 88 894

|
Цитата(jcxz @ Jun 6 2017, 03:35)  Монитор эксклюзивного доступа не контролирует адрес. Об этом явно сказано в мануале. Да и как вы это себе представляете? Если у процессора 4гига адресное пространство - это-ж нужна 4^32 триггеров иметь в CPU - для каждого адреса. Там всё просто, один единственный 32b регистр и схема сравнения на коммутаторе памяти, уже после арбитра и коммутатора нагрузки. Эти команды не выполняются целиком и полностью в ядре мк, они большей частью размазаны по всему кристаллу. Точно так-же как и команды DSB, ISB, ISB, WFE, и так далее.
|
|
|
|
|
Jun 6 2017, 08:20
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(AVI-crak @ Jun 6 2017, 09:24)  Там всё просто, один единственный 32b регистр и схема сравнения на коммутаторе памяти, уже после арбитра и коммутатора нагрузки. Эти команды не выполняются целиком и полностью в ядре мк, они большей частью размазаны по всему кристаллу. Открываем мануал на M4, читаем: "The Cortex-M4 processor implements a local exclusive monitor. The local monitor within the processor has been constructed so that it does not hold any physical address, but instead treats any access as matching the address of the previous LDREX. This means that the implemented exclusives reservation granule is the entire memory address range." Фантазии про некий регистр рассеиваются Влияние доступов от DMA и прочих bus-masters на exclusive monitor - также представляется крайне сомнительным, так как: 1. зачем оно нужно? 2. где про это сказано? 3. exclusive monitor относится к ядру, а DMA- и прочие bus-masters к ядру не относятся и у каждого МК-мэйкера свои.
|
|
|
|
Сообщений в этой теме
_lexa_ __LDREX __STREX в STM32F407 Jun 4 2017, 13:18       AHTOXA Цитата(Forger @ Jun 5 2017, 13:17) Полага... Jun 5 2017, 08:22        Forger Цитата(AHTOXA @ Jun 5 2017, 11:22) Если, ... Jun 5 2017, 08:24         AHTOXA Цитата(Forger @ Jun 5 2017, 13:24) Почему... Jun 5 2017, 08:54            Forger Цитата(jcxz @ Jun 5 2017, 13:50) Надо тол... Jun 5 2017, 11:00             jcxz Цитата(Forger @ Jun 5 2017, 13:00) Не пон... Jun 5 2017, 11:09              Forger Цитата(jcxz @ Jun 5 2017, 14:09) Так как ... Jun 5 2017, 11:18               Forger Попался полезный документ по теме:
http://infocent... Jun 5 2017, 12:22                _lexa_ Цитата(Forger @ Jun 5 2017, 12:22) Попалс... Jun 5 2017, 13:55               jcxz Цитата(Forger @ Jun 5 2017, 13:18) Речь к... Jun 5 2017, 13:47             AHTOXA Цитата(_lexa_ @ Jun 5 2017, 18:26) В тако... Jun 5 2017, 13:51                 _lexa_ Цитата(jcxz @ Jun 5 2017, 21:35) Похоже В... Jun 5 2017, 23:19                   _lexa_ Цитата(jcxz @ Jun 6 2017, 08:20) Открывае... Jun 6 2017, 20:56                   Alechek Цитата(jcxz @ Jun 6 2017, 13:20) Фантазии... Jun 7 2017, 08:31                    jcxz Цитата(Alechek @ Jun 7 2017, 10:31) Опять... Jun 7 2017, 08:56                 KnightIgor Цитата(jcxz @ Jun 5 2017, 22:35) Ну навер... Jun 6 2017, 10:22                  AVI-crak Цитата(jcxz @ Jun 6 2017, 14:20) 1. зачем... Jun 6 2017, 11:02                   KnightIgor Цитата(AVI-crak @ Jun 6 2017, 12:02)... Jun 6 2017, 20:34                    jcxz Цитата(KnightIgor @ Jun 6 2017, 22:34) Ра... Jun 6 2017, 21:36                     LightElf QUOTE (jcxz @ Jun 7 2017, 00:36) Я писал ... Jun 7 2017, 11:52                      Forger Цитата(LightElf @ Jun 7 2017, 14:52) А пр... Jun 7 2017, 12:39                       jcxz Цитата(Forger @ Jun 7 2017, 14:39) Причем... Jun 7 2017, 13:13                        Forger Цитата(jcxz @ Jun 7 2017, 16:13) чтобы, е... Jun 7 2017, 13:27                  jcxz Цитата(KnightIgor @ Jun 6 2017, 12:22) То... Jun 6 2017, 12:08              _lexa_ Цитата(jcxz @ Jun 5 2017, 14:21) Видимо э... Jun 5 2017, 17:40               AVI-crak Цитата(_lexa_ @ Jun 5 2017, 23:40) Спасиб... Jun 5 2017, 18:00                _lexa_ Цитата(AVI-crak @ Jun 5 2017, 18:00)... Jun 5 2017, 19:28      KnightIgor Цитата(AHTOXA @ Jun 5 2017, 06:38) А в чё... Jun 5 2017, 12:40       jcxz Цитата(KnightIgor @ Jun 5 2017, 14:40) Ес... Jun 5 2017, 13:57        KnightIgor Цитата(jcxz @ Jun 5 2017, 14:57)
У меня ... Jun 5 2017, 19:42       AHTOXA Цитата(KnightIgor @ Jun 5 2017, 17:40) Ка... Jun 5 2017, 13:58  jcxz Цитата(_lexa_ @ Jun 4 2017, 20:39) Где-то... Jun 5 2017, 07:49   _lexa_ Цитата(jcxz @ Jun 5 2017, 07:49) Если меж... Jun 5 2017, 10:17   Alechek ЦитатаНе тот мануал открываете
Ну почему же не тот... Jun 7 2017, 09:18    jcxz Цитата(Alechek @ Jun 7 2017, 11:18) Про у... Jun 7 2017, 09:29     Alechek Цитата(jcxz @ Jun 7 2017, 14:29) В смысле... Jun 7 2017, 10:21      scifi Цитата(Alechek @ Jun 7 2017, 13:21) В смы... Jun 7 2017, 10:27      jcxz Цитата(Alechek @ Jun 7 2017, 12:21) В смы... Jun 7 2017, 11:23 Alechek Цитата(scifi @ Jun 7 2017, 15:27) Это наз... Jun 7 2017, 12:22 scifi Цитата(Alechek @ Jun 7 2017, 15:22) Сдела... Jun 7 2017, 12:50 AHTOXA Цитата(Alechek @ Jun 7 2017, 17:22) А поп... Jun 7 2017, 13:30 Alechek AHTOXA, спасибо, ознакомился.
Но, опять противореч... Jun 8 2017, 05:01 jcxz Цитата(Alechek @ Jun 8 2017, 07:01) - LDR... Jun 8 2017, 06:17 AHTOXA Цитата(Alechek @ Jun 8 2017, 10:01) - LDR... Jun 8 2017, 06:21  LightElf QUOTE (AHTOXA @ Jun 8 2017, 09:21) Именно... Jun 8 2017, 13:44   AHTOXA Цитата(LightElf @ Jun 8 2017, 18:44) Есть... Jun 8 2017, 14:52 Alechek Цитата(jcxz @ Jun 8 2017, 11:17) И правил... Jun 8 2017, 11:54 AVI-crak Проверять нужно кодом на асме, чтобы gcc не наопти... Jun 8 2017, 13:21  jcxz Цитата(AVI-crak @ Jun 8 2017, 15:21)... Jun 8 2017, 20:32   Forger Коли SVC синхронное и его не получиться использова... Jun 9 2017, 07:50    jcxz Цитата(Forger @ Jun 9 2017, 09:50) зы. Пр... Jun 9 2017, 10:33     Forger Цитата(jcxz @ Jun 9 2017, 13:33) PendSV н... Jun 9 2017, 10:58      Шаманъ Цитата(Forger @ Jun 9 2017, 13:58) как сд... Jun 9 2017, 13:02       Forger Цитата(Шаманъ @ Jun 9 2017, 16:02) Очеред... Jun 9 2017, 13:20        Шаманъ Цитата(Forger @ Jun 9 2017, 16:20) хочетс... Jun 9 2017, 14:14         Forger Цитата(Шаманъ @ Jun 9 2017, 17:14) Интере... Jun 9 2017, 14:30          Шаманъ Цитата(Forger @ Jun 9 2017, 17:30) При че... Jun 9 2017, 15:40           Forger Цитата(Шаманъ @ Jun 9 2017, 18:40) Это ка... Jun 9 2017, 16:27            Шаманъ Цитата(Forger @ Jun 9 2017, 19:27) Я гово... Jun 9 2017, 17:08             Forger Цитата(Шаманъ @ Jun 9 2017, 20:08) От же ... Jun 9 2017, 17:23              Шаманъ Цитата(Forger @ Jun 9 2017, 20:23) Чтобы ... Jun 9 2017, 17:40               Forger Цитата(Шаманъ @ Jun 9 2017, 20:40) Если н... Jun 9 2017, 17:48                Шаманъ Цитата(Forger @ Jun 9 2017, 20:48) Не, эт... Jun 9 2017, 17:56                 Forger Цитата(Шаманъ @ Jun 9 2017, 20:56) Конечн... Jun 9 2017, 18:04                  Шаманъ Цитата(Forger @ Jun 9 2017, 21:04) И само... Jun 9 2017, 18:54                  jcxz Цитата(Forger @ Jun 9 2017, 20:04) Я дела... Jun 9 2017, 19:37                   Forger Цитата(jcxz @ Jun 9 2017, 22:31) Вот как ... Jun 9 2017, 19:39                    jcxz Цитата(Forger @ Jun 9 2017, 21:39) Самое ... Jun 9 2017, 20:27                   Forger Цитата(jcxz @ Jun 9 2017, 22:37) Допустим... Jun 9 2017, 20:44                    jcxz Цитата(Forger @ Jun 9 2017, 22:44) Понима... Jun 9 2017, 20:58                     Forger Цитата(jcxz @ Jun 9 2017, 23:58) К работе... Jun 9 2017, 21:15                      jcxz Цитата(Forger @ Jun 9 2017, 23:15) Пусть ... Jun 9 2017, 21:20                       Forger Цитата(jcxz @ Jun 10 2017, 00:17) Ещё раз... Jun 9 2017, 21:20                       Forger Цитата(jcxz @ Jun 10 2017, 00:20) Да хоть... Jun 9 2017, 21:27                      jcxz Цитата(Forger @ Jun 9 2017, 23:15) При че... Jun 9 2017, 21:24                    Forger Кстати, при очистке очереди изменяются оба указате... Jun 9 2017, 20:59                     jcxz Цитата(Forger @ Jun 9 2017, 22:59) Кстати... Jun 9 2017, 21:10              jcxz Цитата(Forger @ Jun 9 2017, 19:23) А в фо... Jun 9 2017, 19:18               Forger Цитата(jcxz @ Jun 9 2017, 22:12) И в фоно... Jun 9 2017, 19:18        AVI-crak Защищённый режим: стек для потоков psp, стек для п... Jun 9 2017, 14:38 AHTOXA Цитата(Alechek @ Jun 8 2017, 16:54) Вобще... Jun 8 2017, 13:39
2 страниц
1 2 >
3 чел. читают эту тему (гостей: 3, скрытых пользователей: 0)
Пользователей: 0
|
|
|