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

 
 
3 страниц V  < 1 2 3  
Reply to this topicStart new topic
> Выход из handler-mode в cortex-m3
Omnicake
сообщение May 12 2014, 16:17
Сообщение #31


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 12-01-14
Из: Омск
Пользователь №: 80 002



Видимо действительно у меня нет понимания. Я решаю, извините за каламбур, задачу переключения задач в ассемблере. Для этого хотелось использовать прерывание от системного таймера, так как там вполне ясный и понятный режим срабатывания (время прошло - сработало прерывание - задача сменилась). Про PendSV мне удалось найти только информацию о том, что он пригодится при переключении задач. Но то как его вызывать, как он срабатывает и что делает - нет. Каким образом тогда построить стэк, чтобы при записи числа EXC он правильно подцеплялся?

Сообщение отредактировал Omnicake - May 12 2014, 16:20
Go to the top of the page
 
+Quote Post
adnega
сообщение May 12 2014, 17:03
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(Omnicake @ May 12 2014, 20:17) *
Видимо действительно у меня нет понимания. Я решаю, извините за каламбур, задачу переключения задач в ассемблере. Для этого хотелось использовать прерывание от системного таймера, так как там вполне ясный и понятный режим срабатывания (время прошло - сработало прерывание - задача сменилась). Про PendSV мне удалось найти только информацию о том, что он пригодится при переключении задач. Но то как его вызывать, как он срабатывает и что делает - нет. Каким образом тогда построить стэк, чтобы при записи числа EXC он правильно подцеплялся?

Понимаю тягу к ассемблеру Cortex-M, но считаю, что это всего лишь инструмент.
Для переключения контекста не обязательно писать на Си или Асм - нужно разобраться в архитектуре.
SysTick это всего лишь таймер, одинаковый для всех производителей микроконтроллеров на ядре Cortex-M.
Для переключения задач Вам нужно либо в задаче вызавать системную функцию, в которой произойдет переключение.
Либо переключить задачу по прерыванию. В том числе от таймера. В том числе от таймера SysTick.
Можно переключать задачи в SysTick, но в случае, если SysTick у Вас с самым низким приоритетом - это гарантирует, что Вы точно знаете положение
стекового кадра main. Можно использовать два стека, что в какой-то степени решит проблему вложенных прерываний. Но когда Вы сделаете такой
переключатель задач по таймеру, вряд ли легко сможете переключать задачи где-либо еще. Задачи в некоторый случаях (где есть ассинхронная пауза)
будут "тупить" до момента сработки таймера SysTick.

Если в конце SysTick взводить PendSv (ровно как и в функциях ядра), то переключение будет:
- гарантированно происходить после каждого срабатывания SysTick;
- в функциях ядра;
- гарантированно происходить до момента передачи управления в main.

Идеально. Что при таком подходе Вам не нравится? На Асме красиво реализуется.

Go to the top of the page
 
+Quote Post
Golikov A.
сообщение May 12 2014, 17:56
Сообщение #33


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



1. PendSv - это просто особое прерывание, приоритет которого можно поставить минимальным, это позволит вам быть уверенным что в него вы попали из задачи а не из другого прерывания. В вашем случае PendSV и Прерывания таймера не различимы, задайте таймеру минимальный приоритет, и будет почти тоже самое. То есть во взрослых системах PendSV вызывается во многих случаях, те только через заданное время после прошлого вызова, у вас же только так.

2.
Цитата
LDR sp, [r1,#24];Загрузил стэк программы
MOVW R2,#0x00d0; в котором по адресу 0x200000d0
MOVT R2,#0x2000; положил число 0xFFFFFFF9
LDR pc, [r2]; Загрузил его в PC


чет я не понимаюsm.gif... Видать я как то непонятно пишу... Попробую еще раз.

если вы находитесь в hendlre режиме, как только вы в счетчик команд запишите 0xFFFFFFF9, обращаю внимание именно в счетчик команд, ни в стэк, ни в память, а именно в него. То процессор запустить процедуру выхода из hendler режима в thread режим (он не перейдет по указанному адресу, а запустить процедуру). В ходе этой процедуры процессор из стэка восстановит значения счетчика команд куда ему надо идти. При этом процессор будет использовать главный стэк в случае если на конце 9, и стэк программ если на конце D.
В стэке к моменту записи магического числа должно лежать правильной последовательности PC, LR, r0-r3, и чего-то там еще, то есть полный набор сохраняемых данных для входа в прерывание.

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

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

То есть в начале работы
вам надо сделать задачи со своими локальными стэками
положить в них структуру которая кладется когда вызовиться прерывание из этой задача, в место где хранится РС положить начало вашей задачи.

далее в прерывании вам надо, сохранять PSP задачи из которой пришли, далее РSP устанавливать на стэк нвоой задачи, и записывать магическое число. Все!
Go to the top of the page
 
+Quote Post
1113
сообщение May 12 2014, 17:59
Сообщение #34


Знающий
****

Группа: Свой
Сообщений: 604
Регистрация: 24-02-06
Из: Москва
Пользователь №: 14 658



Цитата(Omnicake @ May 12 2014, 19:17) *
Про PendSV мне удалось найти только информацию о том, что он пригодится при переключении задач. Но то как его вызывать, как он срабатывает и что делает - нет.
как систик, только вызывается не аппаратно а програмно там и тогда когда вам надо. этот эксепшен используют из мэйна для запуска операционки, то есть для входа в первую задачу. ну а все последующие переключения задач - в систик.
Go to the top of the page
 
+Quote Post
Omnicake
сообщение May 13 2014, 02:10
Сообщение #35


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 12-01-14
Из: Омск
Пользователь №: 80 002



Цитата
вам надо сделать задачи со своими локальными стэками
положить в них структуру которая кладется когда вызовиться прерывание из этой задача, в место где хранится РС положить начало вашей задачи.

Локальные стэки я задал, в каждой задаче у меня прописано Stack_task1[512]. LDR sp, [r1,#24] как раз и грузить адрес метки Stack_task1.
А по поводу
Цитата
если вы находитесь в hendlre режиме, как только вы в счетчик команд запишите 0xFFFFFFF9, обращаю внимание именно в счетчик команд, ни в стэк, ни в память, а именно в него.

Может я чего-то не увидел, но напрямую через команду MOV в PC на Cortex M3 вроде бы писать нельзя, компилятор мне выдает ошибку. Да и в инструкции написано, что грузятся значения в PC только через LDR или POP, а для этого нужно магическое число куда-то положить (я и положил его в стэк задачи).
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение May 13 2014, 04:44
Сообщение #36


Гуру
******

Группа: Свой
Сообщений: 4 256
Регистрация: 17-02-06
Пользователь №: 14 454



обращаемся к первоисточнику

http://infocenter.arm.com/help/index.jsp?t...9125006491.html
1. есть мнение что LDR sp - изменит не PSP а MSP, вернее через sp вы вообще меняете 13 регистр, который по сути есть только отображение указателя стэка. А надо менять именно psp или msp

2. положили ли вы в стэк задач http://infocenter.arm.com/help/index.jsp?t...a/Babefdjc.html структуру как на рисуночке с указателями и прочей байдой, где в РС лежит первая команда задачи? А указатель показывает на последнюю непустую ячейку

3.
Exception return occurs when the processor is in Handler mode and executes one of the following instructions attempts to set the PC to an EXC_RETURN value:
an LDM or POP instruction that loads the PC
an LDR instruction with PC as the destination
a BX instruction using any register.

EXC_RETURN - это магическое число. Причем 0xFFFFFFF9 - это возврат через MSP, а 0xFFFFFFFD это возврат через PSP


Третий пункт вы вроде бы выполнили правильно (хотя я воспользовался бы командой BX, наверное), значит остается вопросы к 1, 2 пунктам....
Go to the top of the page
 
+Quote Post
Omnicake
сообщение May 13 2014, 05:34
Сообщение #37


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 12-01-14
Из: Омск
Пользователь №: 80 002



1. Ну у меня и отображается активным MSP все это время, и до прерывания и внутри него. Командой LDR я меняю указатель на метку Stack_task1 - массив из 512 чисел, который я взял за стэк задачи.
2. Как корректно класть туда эту структуру? Заранее прописывать ее в массив в самой задаче или загонять через PUSH необходимые регистры?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 13 2014, 06:34
Сообщение #38


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Omnicake @ May 12 2014, 17:16) *
в симуляторе я могу свободно просматривать память и пошагово следить за программой. После входа в прерывание у меня лежит LR возврата на main,
Начните с чтения документации. В момент входа в обработчик исключения адрес возврата вместе с содержимым некоторых регистров кладется на стек. В LR заносится магическое число. Если вы наблюдаете в LR адрес возврата - выкиньте свой симулятор. Или вы попадаете в исключение каким-то нестандартным методом, вроде прямого вызова функции?


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Omnicake
сообщение May 13 2014, 06:37
Сообщение #39


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 12-01-14
Из: Омск
Пользователь №: 80 002



Цитата
В LR заносится магическое число. Если вы наблюдаете в LR адрес возврата - выкиньте свой симулятор. Или вы попадаете в исключение каким-то нестандартным методом, вроде прямого вызова функции?

Тут возможно я недостаточно подробно описал, при входе в прерывание там действительно лежит число EXC_RETURN но затем, из за того что в обработчике у меня стоит вызов другой программы (а именно переключателя задач), он уходит на ту программу, помещая в LR адрес возврата.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 13 2014, 07:43
Сообщение #40


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Omnicake @ May 13 2014, 09:37) *
он уходит на ту программу, помещая в LR адрес возврата.
Так сохраните старое значение LR куда-нибудь. Например, на стек. И потом со стека восстанавливайте сразу в PC командой POP.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Omnicake
сообщение May 13 2014, 08:11
Сообщение #41


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 12-01-14
Из: Омск
Пользователь №: 80 002



Видимо это Keil uVision и делает: после того как я добавил ассемблерные вставки в main, написанный на C, он создал автоматически файл main.s и там функция
Код
SysTick_Handler
{
scheduler();
}

Выглядит вот так
Код
SysTick_Handler
     PUSH {r4,lr}
     BL systick
     POP {r4,pc}

Однако из-за того, что из systick я прыгаю на другую программу, POP {r4,pc} пропускается. Значит, судя по всему, нужно делать это внутри шедулера.
Go to the top of the page
 
+Quote Post
1113
сообщение May 13 2014, 08:17
Сообщение #42


Знающий
****

Группа: Свой
Сообщений: 604
Регистрация: 24-02-06
Из: Москва
Пользователь №: 14 658



Omnicake, ваше желание разобраться похвально, но такими темпами вы будете делать это ещё полгода. предлагаю вам почитать о coocox os. она написана очень просто, имеет документацию на русском, процедуры переключения контекста написаны на ассемблере, что позволит вам за несколько дней разобраться в сути вопроса.
Go to the top of the page
 
+Quote Post
Omnicake
сообщение May 13 2014, 08:26
Сообщение #43


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 12-01-14
Из: Омск
Пользователь №: 80 002



Хорошо. Спасибо.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 13 2014, 11:47
Сообщение #44


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Omnicake @ May 13 2014, 11:11) *
Однако из-за того, что из systick я прыгаю на другую программу, POP {r4,pc} пропускается.
Так вы вернитесь из "другой подпрограммы". Или, если не собираетесь возвращаться, переходите на SysTick не по BL, а по B. И в LR останется магическое число.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Omnicake
сообщение May 13 2014, 12:53
Сообщение #45


Участник
*

Группа: Участник
Сообщений: 56
Регистрация: 12-01-14
Из: Омск
Пользователь №: 80 002



Починил, правда, для меня, это шаманством осталось. Я говорил выше, что компилятор создает файл main.s вместо main.c, а так как внутри него я не мог ничего редактировать (он создан компилятором) я решил просто скопировать его и заменить им файл main.c, после этого когда я запустил в шедулере этот код:
Код
    LDR        r0,    =TaskPointer
    LDR     r0, [r0]
    LDR     r0, [r0]
    MOV     r1,    r0
    LDR sp, [r1,#24]
    BX  lr

При этом стэк для задачи я задал вручную вот так:
Код
int Stack_task1[512]={0x00000000,0xfffffff9,0x00000007,0xe000e000,0x200021e8,0x200021e8,0x200021
c4,0x08000211,0x08000212,0x21000000};

поместив в него нужные метки и то самое число. С этим стэком я уже запускал до этого (на main.c) и ничего не работало, однако тут удалось: после BX LR он вышел из шедулера на хэндлер, выполнил POP {pc} и прыгнул на задачу. Метод скорее всего "напролом" но от него уже можно плясать. Спасибо всем за советы и помощь, буду работать дальше.
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 Текстовая версия Сейчас: 21st July 2025 - 00:42
Рейтинг@Mail.ru


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