|
__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, 10:22
|
Знающий
   
Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725

|
Цитата(jcxz @ Jun 5 2017, 22:35)  Ну наверное. То есть, предложенное решение не на все случаи? Вы также признаете очевидность, Мистер Андерсон? Цитата А что это за прерывание такое, которое внутри себя запрещает прерывания??? Аппаратное асинхронное? Т.е. - оно может вызваться в любой точке и в произвольный момент времени запретить прерывания? А зачем это нужно и как может такая программа вообще функционировать? Да кто же его знает! Однако, такое возможно. Например, прерывание, сделав дело и установив флаг, запрещает прерывания до момента, пока синхронная часть не обработает флаг и не сочтет нужным прерывание снова разрешить. И Ваш код породит огород, на котором пожнут не то, что сеяли.
Сообщение отредактировал KnightIgor - Jun 6 2017, 10:22
|
|
|
|
|
Jun 6 2017, 11:02
|
Частый гость
 
Группа: Участник
Сообщений: 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, и будет вам счастье.
|
|
|
|
|
Jun 6 2017, 20:34
|
Знающий
   
Группа: Участник
Сообщений: 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
|
|
|
|
Сообщений в этой теме
_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                 AVI-crak Цитата(jcxz @ Jun 6 2017, 03:35) Монитор ... Jun 6 2017, 07:24                  jcxz Цитата(AVI-crak @ Jun 6 2017, 09:24)... Jun 6 2017, 08:20                   _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                    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 >
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|