Перейти к содержанию
    

Вопрос по применению PendSV в простом планировщике

Добрый день. Есть вопрос по правильному применению PendSV в Cortex-M4.

Пару раз использовал простой планировщик, написанный на Си. В нем задачи - это простые функции, которые, в отличии от обычных вытесняющих OS, не содержат в своем теле бесконечного цикла, а выполняются до завершения. Решил добавить задачам приоритеты и добавить возможность более приоритетным задачам приостанавливать менее приоритетные, как в Super Simple Tasker (SST). Как я это вижу:

Стек общий на все задачи. При выполнении задачи (A), если требуется передать управлении более приоритетной (B) - в кольцевой буфер кладём указатель на необходимую задачу и вызываем прерывание PendSV. Попадаем в обработчик прерывания PendSV_Handler (при этом стек предыдущей задачи сохранился, в него мы попадём при выходе из прерывания). В обработчике видим, что есть потребность исполнения более приоритетной задачи B -> вызываем её (как функцию), выполняем, возвращаемся в тело обработчика прерывания и выходим из прерывания, возвращаясь задачу A и продолжаем её выполнение.

Проблема в том, что вызывая задачу В я остаюсь в контексте прерывания PendSV и я не смогу передать (если это потребуется) управление ещё более приоритетной задаче (С), т.к. нельзя ещё раз вызвать прерывание PendSV. Как-то можно это обойти?

Изменено пользователем arhiv6

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть вопрос по правильному применению PendSV в Cortex-M4.

Как-то можно это обойти?

Воспользоваться любой готовой бесплатной RTOS (где есть порт под CM4) или подсмотреть как сделаны обработчики у них, если нравится изобретать велосипед :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

...Стек общий на все задачи. ...

 

Присоединюсь к мысли прозвучавшей выше:

- или по другому = если не использовать опыт ранее накопленный то останешься на уровне обезьяны...

 

сам обычно делаю следующим образом(в похожих случаях):

выбираю из информации в сети более подходящую под задачу ось.

выбираю версию.

форматирую ручками весь текст(заодно и знакомлюсь с потрохами, контролирую ошибки(которые кстати встречаются всегда как правило), переписываю те блоки которые можно решить лучше

в рамках данной задачи.

 

вышесказанное не отменяет знакомство с документацией (естественно), и поиском решения тех или иных проблем в инете.

 

без таких похожих шагов - Вы либо будете строить свой велосипед, либо как пионэр с гранатой.

 

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

Думаю понятно, что одна команда лучше чем несколько:)

 

удачи Вам

(круглый)

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для совсем простых вещей работаю без ОС, для некоторых - хватает упомянутого планировщика, для чего-то сложнее - разумеется, использую готовую ОС. Появилась идея немного доработать планировщик, это скорее для самообразования (для этих же целей, например, писал простой кооперативный планировщик на setjmp/longjmp - чтобы научиться работать с setjmp/longjmp, чтобы на своём опыте попробовать карусельную ОС).

Исходники смотрел. Например, scmRtos - на сколько хватает моего понимания - для каждой задачи выделяется в памяти своя область для хранения стека, в PendSV_Handler происходит сохранение текущего указателя на стек, сохранение регистров, восстановление значений регистров новой задачи, в регистр указателя стека записывается указатель на стек новой задачи и происходит выход из прерывания - и т.к. указатель на стек мы поменял -> автоматически переходим в новую задачу. Но, к сожалению, у меня не хватает знаний о том, какой алгоритм должен быть для переключения задач в моём случае.

Первое, что пришло в голову - использование прерывания и работа в его контексте. При этом при вызове обработчика прерывания автоматически сохранится контекст текущей задачи, создастся новый - для обработчика прерывания. Даже ассемблер не нужен, всё сделает компилятор. Но, т.к. вложенные прерывания запрещены, все ограничивается одним уровнем приоритета. Какие есть средства обойти это? Только использовать подмену адреса в указателе на стек и выходить из обработчика прерывания? Или можно как-то сообщить ядру что обработка прерывания закончена и при этом остаться в контексте прерывания (по сути - разрешить вложенные прерывания)? Или как-то по другому?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для совсем простых вещей работаю без ОС, для некоторых - хватает упомянутого планировщика, для чего-то сложнее - разумеется, использую готовую ОС

По своему опыту уверенно скажу, что право на жизнь имеют тока первый и третий варианты, а второй вариант лучше забыть как кошмарный сон!

В любой проект можно всунуть ОСь и также любой проект может жить без ОСи, но самодельные костыли в виде чего-то промежуточного принесут только горе и страдания ;)

Некоторым, чтобы это понять, все же приходится городить эти костыли, но сука-жисть расставит все на свои места - рано или поздно костыли будут выброшены и навсегда забыты :)

Я так говорю, поскольку сам в свое время баловался этим ...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

По своему опыту уверенно скажу, что право на жизнь имеют тока первый и третий варианты, а второй вариант лучше забыть как кошмарный сон!

 

И в чем там кошмарный сон? Сам использую простой переключатель задач, без всяких очередей и прочих наворотов. Вполне хватает мьютексов и глобальных переменных или структур. ИМХО для себя считаю это простым и понятным.

 

ЗЫ. на этих принципах написана своя графическая операционка, если кто считает, что сложные задачи так не пишутся..

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

И в чем там кошмарный сон?
Я лишь поделился своими впечатлениями ))

 

использую простой переключатель задач, без всяких очередей и прочих наворотов.
В любой готовой ОСи нет никакой нужды использовать все ее фишки. В прошивку попадают только те функции, которые используются, остальное линковщик игнорирует.

post-2831-1474808562_thumb.jpg

 

Под разные ядра я заранее скомпилировал свои ОСи и к каждом проекту подключаю нужную либу, чтобы не подключать все ее исходники. Удобно.

Это касается не только оси, но и других сторонних библиотек.

 

Вполне хватает мьютексов
Согласен, я сам редко использую более "толстые" сервисы ))

 

и глобальных переменных или структур.
Ось дает возможность вообще отказаться от глобальных переменных, т.к. они весьма коварное зло, которое пакостит так, что невозможно понять откуда ноги растут :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Простейший вариант - заюзать приоритеты прерываний. И каждый набор задач одного приоритета дергать из программного прерывания (под которые отдать неиспользуемые аппаратные). При этом автоматом более приоритетная задача вытеснит менее приоритетную.

 

При этом задачи с наименьшим приоритетом будут дергаться прямо из main, дальше идет требуемое кол-во прерываний с разными приоритетами, и затем - аппаратные прерывания

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Даже ассемблер не нужен, всё сделает компилятор.

Очень большое заблуждение. GCC настолько оптимизирует код - что функции ос размазываются по всему контексту. Прямые вставки на асме заставляют выполнятся код в нужном месте, в уникальном порядке.

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

 

Глобальное использование препроцесора, при этом новых задач создать невозможно, так-же как и удалить - но зато моментальный старт.

 

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

 

Третий вариант: статический стек прерываний + динамический стек задач - есно вниз. Динамическое выделение памяти под переменные в области хелпа - есно в верх. Ещё больше гибкости, но и больше накладных расходов.

 

Четвёртый вариант: аналог третьего с небольшим исключением - плавающая граница между нижней планкой стека и верхней планкой памяти переменных. Позволяет впихнуть невпихуемое в самый маленький мк, и заставить двигаться то - что двигаться чисто физически не может. (почти автоваз)

 

Литература для обучения и создания собственной ос http://badembed.ru/assembler-pereklyuchenie-konteksta/

Моё https://bitbucket.org/AVI-crak/rtos-cortex-.../branch/default на орфографию не обращать внимания - это глюки.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В "области хелпа" - я рекомендую разместить heap (;

 

…Тут всего три подхода:

 

Третий вариант: …

 

Четвёртый вариант: …

 

Литература для обучения и создания собственной ос http://badembed.ru/assembler-pereklyuchenie-konteksta/

Моё https://bitbucket.org/AVI-crak/rtos-cortex-.../branch/default на орфографию не обращать внимания - это глюки.

 

 

А за литературу спасибо от души.

 

 

Изменено пользователем Obam

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...