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

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> Cortex и гонки при сне
jcxz
сообщение Mar 29 2016, 08:22
Сообщение #16


Гуру
******

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



Цитата(Kabdim @ Mar 29 2016, 12:30) *
Вчера уткнулся ровно в ту же задачу. Кмк большинство отвечающих слишком привыкли к ртосам. Самому писать кусок с переключением контекстов при отсутсвии ртос - саму написать кусок ртос, непрактично.

А что там непрактичного? Всё переключение контекста - пара десятков команд.
Да и, если бы Вы внимательнее прочитали мой пост, как я писал - необязательно даже делать переключение контекста, достаточно задачу, обрабатывающую флаг, заключить в обработчик PendSV.
Но с переключением контекста - правильнее, так как и стек для задачи будет свой и режим - непривилегированный.

Цитата(Kabdim @ Mar 29 2016, 12:30) *
1. Основной цикл перенести в SVC

Вот это как раз непрактично. Или скорее даже невозможно. Насколько помню - у SVC приоритет выше чем у любого аппаратного прерывания (хотя может путаю), к тому же это - синхронное прерывание.
Но самое главное - а что это Вам даст? Вы и WFI внутри SVC будете выполнять? А в чём тогда разница с фоновой задачей?
А если Вы собираетесь возбуждать SVC внутри ISR аппаратного прерывания - это невозможно, ибо SVC - синхронное прерывание, это не PendSV, в ISR SVC будет вход сразу же, без ожидания выхода из ISR аппаратного прерывания, и последующие аппаратные прерывания будут заблокированы. Попытаетесь запретить - получите HardFault.

Цитата(Kabdim @ Mar 29 2016, 12:30) *
2. Пробуждающий обработчик прерываний меняет режим энергосбережения на слип и устанавливает таймер на ~20 тактов вперед. Даже если в это время сработает WFI, то произойдет быстрый выход из сна.

Ничего не понял. Если он пробуждающий - почему тогда он sleep устанавливает??? Сами себе противоречите....

Не нравится PendSV по каким-то причинам, вместо него можно использовать программное возбуждение любого аппаратного прерывания с приоритетом ниже любого используемого в ПО аппаратного прерывания. Хотя это ничем не отличается от PendSV, которое как раз для таких целей и сделано.
Go to the top of the page
 
+Quote Post
Kabdim
сообщение Mar 29 2016, 11:21
Сообщение #17


Знающий
****

Группа: Свой
Сообщений: 558
Регистрация: 26-11-14
Из: Зеленоград
Пользователь №: 83 842



Цитата(jcxz @ Mar 29 2016, 11:22) *
А что там непрактичного? Всё переключение контекста - пара десятков команд.

Просто зачем? Если дошло до написания переключения контекста не проще ли взять готовую ртос? Вот только потом под это решение нужно переделывать всю остальную прошивку.
Цитата(jcxz @ Mar 29 2016, 11:22) *
Да и, если бы Вы внимательнее прочитали мой пост, как я писал - необязательно даже делать переключение контекста, достаточно задачу, обрабатывающую флаг, заключить в обработчик PendSV.
Но с переключением контекста - правильнее, так как и стек для задачи будет свой и режим - непривилегированный.

Тот пост был всё таки не ответом на ваш пост. sm.gif
Цитата(jcxz @ Mar 29 2016, 11:22) *
Вот это как раз непрактично. Или скорее даже невозможно. Насколько помню - у SVC приоритет выше чем у любого аппаратного прерывания (хотя может путаю), к тому же это - синхронное прерывание.
Но самое главное - а что это Вам даст? Вы и WFI внутри SVC будете выполнять? А в чём тогда разница с фоновой задачей?
А если Вы собираетесь возбуждать SVC внутри ISR аппаратного прерывания - это невозможно, ибо SVC - синхронное прерывание, это не PendSV, в ISR SVC будет вход сразу же, без ожидания выхода из ISR аппаратного прерывания, и последующие аппаратные прерывания будут заблокированы. Попытаетесь запретить - получите HardFault.

На моем камне приоритет - Configurable, но не суть важно. Это была мысль представленная на обсудить, а не конкретная реализация. Да, вы правы, PendSV уместей SVC для этой реализации этого решения.
Цитата(jcxz @ Mar 29 2016, 11:22) *
Ничего не понял. Если он пробуждающий - почему тогда он sleep устанавливает??? Сами себе противоречите....

Что б при если после выхода вывалились на команду WFI заснули не в какой-нибудь deep power down, а в более гуманный ко времени просыпа sleep. Впрочем решение не слишком удачное, с этим я не спорю.
Цитата(jcxz @ Mar 29 2016, 11:22) *
Не нравится PendSV по каким-то причинам, вместо него можно использовать программное возбуждение любого аппаратного прерывания с приоритетом ниже любого используемого в ПО аппаратного прерывания. Хотя это ничем не отличается от PendSV, которое как раз для таких целей и сделано.

Нравится, нравится. sm.gif Но решение с просыпанием с pend прерыванием нравится больше, чем возможность навелосипедить собственный кусочек ртос.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 29 2016, 12:13
Сообщение #18


Гуру
******

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



Цитата(Kabdim @ Mar 29 2016, 17:21) *
Нравится, нравится. sm.gif Но решение с просыпанием с pend прерыванием нравится больше, чем возможность навелосипедить собственный кусочек ртос.

Что там велосипедить? rolleyes.gif
CODE
OS_CPU_PendSVHandler:
CPSID I ;Prevent interruption during context switch
MRS R0, PSP ;PSP is process stack pointer
LDR R1, =OSGlobalV
CBZ R0, OS_CPU_PendSVHandler_pop ;Skip register save the first time
STMFD R0!, {R4-R11} ;Save remaining regs r4-11 on process stack
LDR R2, [R1, #OSTCBCur] ;OSTCBCur->OSTCBStkPtr = SP;
STR R0, [R2] ;R0 is SP of process being switched out
;At this point, entire context of process has been saved
OS_CPU_PendSVHandler_nosave:
#if OS_CPU_HOOKS_EN > 0 && OS_TASK_SW_HOOK_EN > 0
PUSH {LR} ;Save LR exc_return value
LDR R0, =OSTaskSwHook ;OSTaskSwHook();
BLX R0
POP {LR}
LDR R1, =OSGlobalV
#endif

LDRB R0, [R1, #OSPrioHighRdy] ;OSPrioCur = OSPrioHighRdy;
STRB R0, [R1, #OSPrioCur]
LDR R0, [R1, #OSTCBHighRdy] ;OSTCBCur = OSTCBHighRdy;
STR R0, [R1, #OSTCBCur]

LDR R0, [R0] ;R0 is new process SP; SP = OSTCBHighRdy->OSTCBStkPtr;
LDMFD R0!, {R4-R11} ;Restore r4-11 from new process stack
MSR PSP, R0 ;Load PSP with new process SP
ORR LR, LR, #0F4h ;;;#4 ;Ensure exception return uses process stack
CPSIE I
BX LR ;Exception return will restore remaining context

OS_CPU_PendSVHandler_pop:
ADDS SP, SP, #(8 * 4)
B OS_CPU_PendSVHandler_nosave
END

Вот и всё. А если не нужно сохранять контекст FPU, то содержимое #if/#endif тоже можно опустить (если нужно - надо ещё добавить сохранение регистров FPU сюда).
Go to the top of the page
 
+Quote Post
AVI-crak
сообщение Mar 29 2016, 23:31
Сообщение #19


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

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



Цитата(jcxz @ Mar 29 2016, 19:13) *
Что там велосипедить? rolleyes.gif


Запрет прерываний CPSID I - это и есть большой глабля. Подобные грабли есть практически во всех мобильных ОС "реального времени". Но прикол в том что при запрете прерываний - перестаёт создаваться очередь этих самых прерываний согласно приоритетам, то-есть банально теряются прерывания. Шанс маленький, да и поймать его достаточно сложно - но сам факт накладывает ограничения на реальность. В идеале ос должна быть без запретов прерываний, а такой финт можно реализовать только через SVC.

Цитата(jcxz @ Mar 29 2016, 15:22) *
А если Вы собираетесь возбуждать SVC внутри ISR аппаратного прерывания - это невозможно, ибо SVC - синхронное прерывание, это не PendSV, в ISR SVC будет вход сразу же, без ожидания выхода из ISR аппаратного прерывания, и последующие аппаратные прерывания будут заблокированы. Попытаетесь запретить - получите HardFault.


Без запретов прерываний - вызов SVC возможен из любого места, в любом режиме работы ядра. Живая очередь прерываний по приоритетам будет продолжать создаваться в фоне, без какого-либо лага.

Собственно моя ос - http://forum.ixbt.com/topic.cgi?id=48:11735
репозиторий https://bitbucket.org/AVI-crak/rtos-cortex-m3-gcc/commits/

Тот самый кусок кода - который отправляет ядро в сон по условию единственной оставшийся в конвертере нулевой задачи, когда в нулевой нет задач на обработку. То-есть момент когда чип сделал всё что от него требуется, и ожидает внешнего события.
Код
sTask_nil_re:
            ldr     r5, [r12, #12]          // адрес задач на обработку памяти
            cbnz    r5, sTask_nil_nw
            ldr     r0, [r12]
            ldr     r1, [r0]
            cmp     r0, r1                  // активная единственная нулевая
            ittt    ne                       // то ждём физики
            movne   r3, 0x10
            svcne   0x0                     // __switch 0x10
            bne     sTask_nil_re
            wfi
            b       sTask_nil_re
sTask_nil_nw:


В линейном коде без ос - достаточно языка С.
do { __WFI(); } while(флаг);
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Mar 30 2016, 01:59
Сообщение #20


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(AVI-crak @ Mar 30 2016, 03:31) *
Запрет прерываний CPSID I - это и есть большой глабля. Подобные грабли есть практически во всех мобильных ОС "реального времени". Но прикол в том что при запрете прерываний - перестаёт создаваться очередь этих самых прерываний согласно приоритетам, то-есть банально теряются прерывания. Шанс маленький, да и поймать его достаточно сложно - но сам факт накладывает ограничения на реальность.

Что за источник это утверждает? Глобальный запрет прерываний флагом I регистра CPSR/PSR должен только запрещать их исполнение.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
AVI-crak
сообщение Mar 30 2016, 03:30
Сообщение #21


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

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



Цитата(GetSmart @ Mar 30 2016, 08:59) *
Что за источник это утверждает? Глобальный запрет прерываний флагом I регистра CPSR/PSR должен только запрещать их исполнение.

Именно так.
В дополнение - изначально Base priority mask register содержит 8 бит для определения приоритета, хотя в Cortex используется только 4 бита. При новом прерывании с более высоким уровнем внутри уже работающего - выставляется признак вложенного прерывания в Priority mask register. Это для управления возвратом из нового прерывания. При этом сравнение уровня прерывания происходит в момент его события.
При запрете прерываний - и возникновении двух и более новых прерываний с разными уровнями - разрулить конечное состояние уже не получится.
По этому запоминается первая регистрация нового прерывания, а всё остальное - игнорируется.
В доках инфа на эту тему очень смутная. Проще проверить практически.
Go to the top of the page
 
+Quote Post
Alechek
сообщение Mar 30 2016, 04:24
Сообщение #22


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

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



Дейсвтельно мутно. Как оно может ПОТЕРЯТСЯ?
Особенно, если оно приходит от периферии и сбрасывается только после выполнения некоторых действий.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 30 2016, 05:32
Сообщение #23


Гуру
******

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



Цитата(AVI-crak @ Mar 30 2016, 05:31) *
Но прикол в том что при запрете прерываний - перестаёт создаваться очередь этих самых прерываний согласно приоритетам, то-есть банально теряются прерывания. Шанс маленький, да и поймать его достаточно сложно - но сам факт накладывает ограничения на реальность.

Бред!
При запрете прерываний они не теряются, а копятся в регистре запросов ожидающих прерываний. Как только прерывания будут разрешены, будет выбрано одно из ожидающих прерываний с наивысшим приоритетом и перейдёт в стадию обслуживания. Любая периферия на МК Cortex_M выдаёт прерывания "по уровню", т.е. - держит запрос пока он не будет обслужен.
И все эти страшилки про "грех запрета прерываний" - байки. Конечно запрет прерываний вносит задержку в обслуживание. Но система уже должна проектироваться с учётом этого и устойчивой к задержкам обработки прерываний, это особенности облуживания прерываний в любой системе на любом МК - всегда есть какая-то задержка, больше или меньше.

Цитата(AVI-crak @ Mar 30 2016, 05:31) *
В идеале ос должна быть без запретов прерываний, а такой финт можно реализовать только через SVC.

SVC разработчиками ядра вообще не для этого задумывался. Соотвественно: такое использование его - неоптимально.

Цитата(AVI-crak @ Mar 30 2016, 05:31) *
Без запретов прерываний - вызов SVC возможен из любого места, в любом режиме работы ядра. Живая очередь прерываний по приоритетам будет продолжать создаваться в фоне, без какого-либо лага.

Ну да - как же. Попробуйте вызвать SVC при запрещенных исключениях. Или изнутри ISR с более высоким приоритетом (точно не помню - можно ли перепрограммировать приоритет SVC, но кто-то выше утверждал что можно).
Получите HardFault. Так как SVC - синхронное прерывание. А для задачи ТСа нужно асинхронное. Типа PendSV (или любого аппаратного, возбуждаемого программно через регистр запросов NVIC).

Цитата(AVI-crak @ Mar 30 2016, 05:31) *
В линейном коде без ос - достаточно языка С.
do { __WFI(); } while(флаг);

Вы даже не поняли исходного вопроса ТС и того, чего он боится. А именно - случаев ухода в сон при установленном флаге требования обработки, когда эта обработка делается в том же процессе, который вызывает WFI. Полностью устранить эту проблему, можно только вынеся обработку флага в отдельный ISR или процесс (также запускаемый по прерыванию).

Цитата(AVI-crak @ Mar 30 2016, 09:30) *
Именно так.
В дополнение - изначально Base priority mask register содержит 8 бит для определения приоритета, хотя в Cortex используется только 4 бита. При новом прерывании с более высоким уровнем внутри уже работающего - выставляется признак вложенного прерывания в Priority mask register. Это для управления возвратом из нового прерывания. При этом сравнение уровня прерывания происходит в момент его события.
При запрете прерываний - и возникновении двух и более новых прерываний с разными уровнями - разрулить конечное состояние уже не получится.
По этому запоминается первая регистрация нового прерывания, а всё остальное - игнорируется.
В доках инфа на эту тему очень смутная. Проще проверить практически.

Регистр маски приоритетов очевидно используется для маскирования запросов с более низким приоритетом и влияет только на активацию нового прерывания, но никак не возврат.
Для возврата используется регистр LR, который указывает из какого режима CPU был вход в ISR и по какому стеку осуществлять возврат.
В доках всё описано кристалльно понятно. Прочитайте их!
И про два и более прерываний - там всё есть. Опять-же - RTFM!
Go to the top of the page
 
+Quote Post
ViKo
сообщение Mar 30 2016, 06:07
Сообщение #24


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Не нашел, чтобы кто-то из участников данной дискуссии упомянул бит SLEEPONEXIT в SCR. Который для того и предназначен.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 30 2016, 06:20
Сообщение #25


Гуру
******

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



Цитата(ViKo @ Mar 30 2016, 12:07) *
Не нашел, чтобы кто-то из участников данной дискуссии упомянул бит SLEEPONEXIT в SCR. Который для того и предназначен.

Предназначен для чего? Для сна в фоновом процессе и работы только в ISR. Можно и его использовать вместо WFI в цикле, но разницы особой нет - мой вариант с обработкой флага внутри ISR PendSV будет работать и с этим битом и с простым циклом while (1) __WFI(); - разницы почти никакой, цикл просто заменится на просто while (1);
Только ведь ТС хочет именно в фоновом процессе обслуживать свой флаг! а тогда этот бит не подходит. sad.gif
Ну не хочет он никак обслуживать свой флаг внутри ISR. Тут - хозяин - барин. laughing.gif
Go to the top of the page
 
+Quote Post
AVI-crak
сообщение Mar 30 2016, 06:38
Сообщение #26


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

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



Цитата(jcxz @ Mar 30 2016, 12:32) *
Бред!
При запрете прерываний они не теряются, а копятся в регистре запросов ожидающих прерываний. Как только прерывания будут разрешены, будет выбрано одно из ожидающих прерываний с наивысшим приоритетом и перейдёт в стадию обслуживания.

Действительно бред, записать в один регистр сразу кучу прерываний.

Вложенность прерываний организованна по подобию стека. Соответственно в один момент может быть доступно всего одно активное прерывание, при запрете оно и регистрируется. В момент регистрации определяется как будет осуществятся возврат из него.
Для разных состояний ядра arm - это разные точки восстановления, их всего 4 штуки. Дык вот, в момент действующего прерывания - этот адрес поддержки ядра уже использован. По заложенному сценарию после снятия запрета - можно будет выполнить одно дополнительное вложенное прерывание. Потому-что невозможно прописать адрес возврата для прерывания которое ещё не исполнилось, но имеет иной уровень приоритета.
Отсебятина в регистре возврата прерывания в режиме ос - типа 0xFFFFFFFD - это и есть указатель на этот регистр. Это значение lr пишется в стек при вложенном новом прерывании более высокого уровня. Всё пля, стек прерываний закрыт. Напомню - в ос вся система крутится на самом слабом прерывании. Это сделано для того чтобы всё содержимое стека прерываний было выгружено, и состоялся переход на стек потока.

Время отведённое для определения приоритета прерывания, а так-же установки адреса для чтения вектора - равно одному такту. Там просто нет возможности сравнивать все 15 уровней. Аппаратная возможность сравнения приоритета работает только в одну сторону - между действующим прерыванием и новым/отложенным более низким. Сравнить отложенное более высокое с новым низким отложенным - просто невозможно.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 30 2016, 07:41
Сообщение #27


Гуру
******

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



Цитата(AVI-crak @ Mar 30 2016, 12:38) *
Действительно бред, записать в один регистр сразу кучу прерываний.

В регистре находятся флаги запросов. Что в этом такого сверхъестественного? Каждый запрос - один бит. Что тут невозможного? А приоритеты для этих запросов - в другом регистре.

Цитата(AVI-crak @ Mar 30 2016, 12:38) *
Время отведённое для определения приоритета прерывания, а так-же установки адреса для чтения вектора - равно одному такту. Там просто нет возможности сравнивать все 15 уровней. Аппаратная возможность сравнения приоритета работает только в одну сторону - между действующим прерыванием и новым/отложенным более низким. Сравнить отложенное более высокое с новым низким отложенным - просто невозможно.

Не понимаю - Вы чего доказать-то пытаетесь?
Что аппаратно сравнить несколько уровней приоритета невозможно? Откройте любой учебник по цифровой электронике. Никаких проблем в этом нет, хоть за полтакта.
Что процессор не сможет из двух ожидающих прерываний выбрать одно с наивысшим приоритетом и обслужить его первым, а затем - второе (если не пришло за это время более приоритетного)? Это противоречит здравому смыслу и докам на ядро, где это описывается. Если бы такое реально происходило, то после первого же запрета прерывания, во время которого успело прийти хотя-бы пару прерываний, происходила потеря прерываний и вообще нормальное функционирование было-бы невозможно. Миллионы устройств на Cortex-M работающих с кучей периферии с прерываниями и множественными запретами оных в коде - говорят об обратном.
Go to the top of the page
 
+Quote Post
ataradov
сообщение Mar 30 2016, 07:54
Сообщение #28


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

Группа: Участник
Сообщений: 1 014
Регистрация: 8-01-07
Из: San Jose, CA
Пользователь №: 24 202



QUOTE (jcxz @ Mar 29 2016, 22:32) *
Полностью устранить эту проблему, можно только вынеся обработку флага в отдельный ISR или процесс (также запускаемый по прерыванию).
Полностью эту проблему устраняют 5 строчек кода на чистом Си приведенные выше.

Все остальные - продолжайте переключать контексты, если сильно хочется, я этой фигней страдать не буду.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Mar 30 2016, 08:19
Сообщение #29


Гуру
******

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



Цитата(ataradov @ Mar 30 2016, 13:54) *
Все остальные - продолжайте переключать контексты, если сильно хочется, я этой фигней страдать не буду.

Вы даже не прочитали, то что Вам советовали. Зачем тогда спрашивали? Просто чтобы "потрещать"?

PS: И переключали и будет переключать, ибо не использовать ОС на ядрах класса Cortex имеет смысл только для очень простых задач, коих не имеем wink.gif
Go to the top of the page
 
+Quote Post
ataradov
сообщение Mar 30 2016, 08:23
Сообщение #30


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

Группа: Участник
Сообщений: 1 014
Регистрация: 8-01-07
Из: San Jose, CA
Пользователь №: 24 202



QUOTE (jcxz @ Mar 30 2016, 01:19) *
Вы даже не прочитали, то что Вам советовали.


Прочитал.

QUOTE (jcxz @ Mar 30 2016, 01:19) *
Зачем тогда спрашивали? Просто чтобы потрещать"?

Чтобы получить разумный совет. Разумный совет как всегда нашелся на англоязычном форуме. К сожалению я успел задать вопрос тут. Это больше не повторится, а то опять придется выслушивать пиписькомеряние.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 5th July 2025 - 09:32
Рейтинг@Mail.ru


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