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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> Переключение задач на STM32f10x в Keil
Omnicake
сообщение May 7 2014, 02:17
Сообщение #1


Участник
*

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



Здравствуйте, пытаюсь сделать простейший переключатель задач на миксе ассемблера и си, используя микропроцессор STM32f10x и среду Keil uVision 5, но постоянно натыкаюсь на непонятные моменты. У меня есть основная функция main, из которой инициализируется процессор и включается таймер systick, по прерыванию таймера запускается диспетчер, в котором я хочу сохранить состояние регистров и при выходе выйти уже не на main а на задачу.
Задачи оформлены в виде c-файлов task1.c task2.c и.т.д., к каждой задаче прикреплена структура(массив из 8 чисел) в который заносятся данные о статусе программы, ее длительности и значения SP и PC-регистров, а также зарезервирована величина стэка командой int Stack_task1[512];. Под все это дело организован еще один массив с указателем на массивы каждой из задач. В теории, при инициализации я должен загрузить в массив для каждой задачи значения SP и PC регистров, чтобы после сохранения/восстановления регистров загрузить в регистры SP и PC числа из массива и командой BX выйти на задачу, до следующего срабатывания таймера.
Однако здесь у меня возник вопрос: как мне узнать значения регистров SP и PC для каждой задачи, если она нигде не запускается? То есть она просто прикреплена к проекту, на нее ссылается массив но при выполнении программы она не выполняется нигде. ТАкже мне известно, что у STM32 два SP регистра, один из которых работает в прерывании, а другой в главной программе. Получается если я перед самым выходом из прерывания изменю значение SP, мне это не поможет, потому что после выхода оно все равно сбросится на то значение, которое было до входа в прерывание? В общем, возможно, вопросы глупые, но сам до додуматься до решения пока не могуЮ потому прошу совета. Заранее спасибо.
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение May 7 2014, 04:54
Сообщение #2


Гуру
******

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



вроде как при написании диспетчера из прерывания не выходят.... То есть основная идея что вы всегда как бы в прерывании, которое разрешает вложенные прерывания, и прерывает само себя. Вроде как - то так было. А счетчики команд и стэка задач надо инициализировать при создании нитки и потом уже за ними следить. Как - то так...

Правда оговорюсь, я пока только теоретически подкован, ручками этого не делал....
Go to the top of the page
 
+Quote Post
Forger
сообщение May 7 2014, 05:48
Сообщение #3


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

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



Цитата(Omnicake @ May 7 2014, 06:17) *
Здравствуйте, пытаюсь сделать простейший переключатель задач на миксе ассемблера и си...

ЗАЧЕМ???
Ведь есть готовые OS в исходниках под это камень и среду в т.ч, где все УЖЕ СДЕЛАНО как нужно и где все отлажено и работает как надо!




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


Гуру
******

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



Цитата(Golikov A. @ May 7 2014, 10:54) *
вроде как при написании диспетчера из прерывания не выходят.... То есть основная идея что вы всегда как бы в прерывании, которое разрешает вложенные прерывания, и прерывает само себя. Вроде как - то так было. А счетчики команд и стэка задач надо инициализировать при создании нитки и потом уже за ними следить. Как - то так...

В реале - не совсем так.
Переключатель контекста (задач) это собсно - ISR. Для Cortex - конкретно PendSV. И должен быть самым низкоприоритетным из всех прерываний.
В нём переключается контекст (стек) задачи Thread-режима. Все задачи выполняются в Thread-режиме, обработчики (и PendSV) - в Handler-режиме.
Выход из Handler - возврат к выполнению задачи (возможно новой, если было переключение в PendSV).
Для переключения задачи из Thread-режима необходимо программно возбудить прерывание PendSV.
PendSV собсно и создано для операционок.
Это вкратце.

Цитата(Forger @ May 7 2014, 11:48) *
Ведь есть готовые OS в исходниках под это камень и среду в т.ч, где все УЖЕ СДЕЛАНО как нужно и где все отлажено и работает как надо!

Товарищ изобретает велосипед.
Изобретать будет долго и получится он с квадратными колёсами, так как читать доки не хочет (ибо - писатель, а не читатель wink.gif и изучать существующие ОС тоже не хочет.
Если-бы хоть что-то прочитал про режимы Cortex, его регистры, обработку прерываний/исключений, то глупых вопросов не задавал-бы.
Ибо начинать надо всегда с глубокого изучения вопроса и читать-читать долго и долго, и только когда всё прояснится, тогда и только тогда можно начинать что-то писать.
А если начинает с писания, то ничего путнего никогда не получится....
Go to the top of the page
 
+Quote Post
RabidRabbit
сообщение May 7 2014, 06:54
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040



Цитата(Omnicake @ May 7 2014, 06:17) *
Однако здесь у меня возник вопрос: как мне узнать значения регистров SP и PC для каждой задачи, если она нигде не запускается? То есть она просто прикреплена к проекту, на нее ссылается массив но при выполнении программы она не выполняется нигде. ТАкже мне известно, что у STM32 два SP регистра, один из которых работает в прерывании, а другой в главной программе. Получается если я перед самым выходом из прерывания изменю значение SP, мне это не поможет, потому что после выхода оно все равно сбросится на то значение, которое было до входа в прерывание?

Про то, как и что сохраняется в стеке - смотрите ARMv7-M Architecture Reference Manual, главу "Exception entry behavior". Далее, если специально не заморачиваться, считайте, что у Вас один регистр SP. Второй задействуется только если Вы специально захотели использовать исполнение кода в "непривелегированном" режиме.
В стеке для каждой задачи перед первым их запуском необходимо проинициализировать "сохранённые регистры", что-то вроде
xPSR, ReturnAddress(), LR (R14), R12, R3, R2, R1, and R0. PC (ReturnAddress()) устанавливается равным адресу функции задачи (task1() или task2() у Вас). xPSR - читайте руководство, что там должно быть. Остальные регистры - по вкусу. При возврате из прерывания SP должен содержать адрес xPSR той задачи, на которую осуществляется переключение.
Как-то так. И ещё раз - читайте мануалы и разглядывайте исходники портов RTOS для STM32, очень поможет в понимании.


Go to the top of the page
 
+Quote Post
adnega
сообщение May 7 2014, 07:49
Сообщение #6


Гуру
******

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



Я бы посоветовал почитать "Джозеф Ю. Ядро Cortex-M3 компании ARM".
Go to the top of the page
 
+Quote Post
Golikov A.
сообщение May 7 2014, 07:53
Сообщение #7


Гуру
******

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



Цитата
В реале - не совсем так.

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

Код
Товарищ изобретает велосипед.

я тоже как то писал архиватор без углубления в теорию, просто потому что было интересно посмотреть сработает или нет, проверить принцип. Проверил, сработало, эффективность мизерная, но сам факт! Это я к тому что для изобретения велосипеда с теорией и без могут быть разные предпосылки.
Go to the top of the page
 
+Quote Post
jcxz
сообщение May 7 2014, 08:50
Сообщение #8


Гуру
******

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



Цитата(Golikov A. @ May 7 2014, 13:53) *
ну то есть в реальности выход из прерывания имеется. Просто есть одно прерывание которое переключает задачи, и из него выходим в конкретную выбранную задачу? И оно же сохраняет все потраха предыдущей задачи из которой его дернули?

В реальности любое переключение контекста - это выход из прерывания.
Т.е. - исполняется ваша задача (в thread-mode) ===>>
происходит прерывание (либо PendSV (вызванное программно из этой-же самой задачи) либо любое другое аппаратное или исключение) ===>>
контекст прерванной задачи сохраняется частично аппаратно (механизм Stacking: R0-R3, R12, SP, PC, PSR) частично программно (остальные регистры на входе в ISR) на стеке ===>>
в этот момент, так как находимся внутри ISR, то активным является MSP, а на прерванный контекст указывает PSP (это если прерван thread-mode, а не handler-mode) ===>>
если это обработчик PendSV, то он проверяет необходимость переключения задачи, если нужно переключать -
просто сохраняет указатель из PSP в текущий указатель стека в дескрипторе данных прерванной задачи, а в PSP загружает значение текущего указателя стека из
дескриптора данных новой задачи (которая теперь будет исполняться) ===>>
дальше - просто выходит из прерывания, а так как PSP теперь указывает на новую задачу, то после выхода будет продолжено выполнение уже её, как будто прерыванием
была прервана она, а не старая задача. Вот и всё.

Такой механизм позволяет делать запрос на переключение задач хоть на уровне задачи, хоть внутри ISR - это будет отрабатываться единообразно.

Так как PendSV имеет низший приоритет, то соответственно он не может прервать другой ISR, и не нужно в нём делать проверку случая прерывания другого ISR
(и соответственно прерванным всегда будет PSP). Такой метод переключения задач хорошо совместим и с механизмом вложенных прерываний Cortex и с механизмом tail-chaining.
Не требует много телодвижений для переключения (как например было в ARM7/ARM9 - там ужас какие выкрутасы приходилось делать с множественными переключениями режимов и копированиями контекстов).
Исходники самого переключателя контекстов у Cortex и у ARM7/9 отличаются по объёму в разы.

Естественно - перед стартом ОС, стеки всех задач должны быть проинициализированы правильно (так как будто эта задача была прервана прерыванием), а в дескрипторах задач должны быть указатели на верхушки стеков.
Go to the top of the page
 
+Quote Post
Omnicake
сообщение May 7 2014, 08:52
Сообщение #9


Участник
*

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



Если честно, разработка диспетчера (то самое изобретение велосипеда) это студенческая работа, которая по определенным обстоятельствам мне досталась и относится не совсем к моей специальности. К сожалению большинство руководств по микропроцессорам написано на английском, и понять оттуда я могу только основную суть, именно поэтому выбрал такой способ обучения, скажем так от знающих людей напрямую. Если я оскорбил чьи-то чувства своими вопросами, заранее извиняюсь. Но мне посоветовали обращаться за помощью именно на этот форум,и именно тут мне до этого давали действительно дельные советы, а не посылали куда подальше.
Go to the top of the page
 
+Quote Post
jcxz
сообщение May 7 2014, 09:08
Сообщение #10


Гуру
******

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



Так Вас и тут никуда дальше мануалов не посылали. А это как раз и есть дельный совет wink.gif
К тому-же я только что почти подробно расписал весь механизм переключения задач в Cortex-M.
А то что не можете найти описание (да хоть и на русском) на одно из самых распространённых ядер в настоящее время,
говорит о том что плохо ищете.
А перепостить сюда выдержки из мануалов - это значит просто захламлять форум.
"Имеющий уши - да услышит, имеющий глаза - да увидит".
Go to the top of the page
 
+Quote Post
Omnicake
сообщение May 7 2014, 09:13
Сообщение #11


Участник
*

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



Хорошо, буду искать. Спасибо. Хотя мне казалось что в переключении использовалось прерывания с системного таймера, дабы обеспечивать режим "реального времени", или прерывание PendSV тоже имеет ограничение по времени?
Go to the top of the page
 
+Quote Post
Forger
сообщение May 7 2014, 09:25
Сообщение #12


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

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



Цитата(Omnicake @ May 7 2014, 12:52) *
Если честно, разработка диспетчера (то самое изобретение велосипеда) это студенческая работа, которая по определенным обстоятельствам мне досталась и относится

Скачивайте исходники любой ОС, имеющией "порт" под cortex-m3.
Например: freertos, tnkernel, ucos.
Там же в доке будет расписан механизм работы переключателя контекста задач.

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


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


Гуру
******

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



Цитата(Omnicake @ May 7 2014, 15:13) *
Хорошо, буду искать. Спасибо. Хотя мне казалось что в переключении использовалось прерывания с системного таймера, дабы обеспечивать режим "реального времени", или прерывание PendSV тоже имеет ограничение по времени?

какое ограничение по времени?
В прерывании таймера обычно ставится только запрос PendSV. Это чтобы всё переключение делалось в одном месте и не нужны были блокировки.
И PendSV должно иметь низший приоритет, ниже любого другого ISR, в том числе таймера, чтобы не мешать работе аппаратных прерываний (не мешать "реальному времени").
Я уже писал об этом выше.
А если вы сделаете в таймере, то как раз это будет хуже с точки зрения реалтаймовости, так как переключение будет на уровне приоритета аппаратного прерывания таймера.

Цитата(Forger @ May 7 2014, 15:25) *
По-моему, значительно проще скачать и изучить уже готовое, под нужде переделав его под себя, чем все это изобретать с нуля sm.gif

...тем более когда вы это изобретёте, если всё сделаете правильно, то с удивлением обнаружите, что ваш код полностью совпадает с уже существующим biggrin.gif
Go to the top of the page
 
+Quote Post
Omnicake
сообщение May 7 2014, 09:50
Сообщение #14


Участник
*

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



Я скачал исходники FreeRTOS и первое на что обратил внимание - это то, что он написан на C, а я видимо забыл упомянуть, что диспетчер я делаю на ассемблере.
Go to the top of the page
 
+Quote Post
RabidRabbit
сообщение May 7 2014, 09:54
Сообщение #15


Местный
***

Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040



Цитата(jcxz @ May 7 2014, 13:44) *
В прерывании таймера обычно ставится только запрос PendSV. Это чтобы всё переключение делалось в одном месте и не нужны были блокировки.

Небольшой хинт: для того, чтобы выставить запрос на PendSV, нужно установить бит PENDSVSET в регистре процессора "Interrupt Control State Register (ICSR)". После этого, когда обстановка позволит, процессор выполнит обработчик PendSV и переключит задачу (если надо).

По поводу исходников на Си - скомпилируйте без оптимизации и посмотрите на ассемблерный листинг sm.gif

Go to the top of the page
 
+Quote Post

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

 


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


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