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

Переключение задач на STM32f10x в Keil

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

Скачайте порт Cortex-M для uCOS. Там всё на асм. И очень лаконично.

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


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

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

Не все там на С, переключатели контекста (порты) написаны на ассемблере. Так организована практически любая ОС.

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


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

С Си на Асм перейти правда 5 копеек задача, компильнул и смотри листинг, обратно муторно, а впрямую то нет проблем.

 

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

 

Единственный момент, мне казалось что переключение задач запускает все же таймер, время отведенное на задачу определяет приоритет потока, так? То есть по выходу интервала таймера он ставит флаг PendSV, и уже тот вызвавшись все делает, так?

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


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

Единственный момент, мне казалось что переключение задач запускает все же таймер,

Нет. Не должен таймер, но может. Задача может сама впасть в ожидание и переключить поток исполнения.

 

время отведенное на задачу определяет приоритет потока, так?

 

Хотелось бы, но чему равно это время - вопрос. От схемы зависит и т.д.

И прерывания могут длится не известно сколько...

 

То есть по выходу интервала таймера он ставит флаг PendSV

Если надо, то ставит, если не надо, то не ставит.

 

PendSV

 

PendSV переключает, если вызовут...

 

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


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

Прочитал в книге "Джозеф Ю. Ядро Cortex-M3 компании ARM" (спасибо кстати тому, кто посоветовал) по поводу прерывания PendSV, и меня смутило что он ждет завершения обработки других прерываний, хотя по идее в ОС реального времени они бывают иногда запрещены. В то время systick делает на мой взгляд то, что нужно: запускается программа -> выполняет несколько шагов -> приходит исключение от systick -> сохраняется контекст -> запускается диспетчер, который определяет переключать или не переключать задачу -> задача переключается/не переключается -> контекст восстанавливается.

В итоге в голове у меня сложилась такая схема того, что мне нужно сделать:

1) В начале инициализации главной подпрограммы main в дескрипторы каждой из задача должны быть загружены значения sp для каждой свой, и значения pc - которое нужно брать от метки каждой из задач.

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

3) В случае переключения я должен изменить указатель дескрипторов на следующую задачу, сместив его на 32 бита.

4) По окончанию всех операций в диспетчере восстановить состояние регистров, которые не восстанавливаются, выгрузить из дескриптора значения PC и SP и прыгнуть по адресу в PC регистре (то есть на задачу).

Однако не получится ли так, что несмотря на то, что я выгрузил значения SP для задачи а потом, выйдя из прерывания, SP снова переписалось на то значение, которое было до прерывания? И получится что указатель стэка не изменился.

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


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

Единственный момент, мне казалось что переключение задач запускает все же таймер, время отведенное на задачу определяет приоритет потока, так? То есть по выходу интервала таймера он ставит флаг PendSV, и уже тот вызвавшись все делает, так?

Я не рассматривал операционок, где ведётся контроль времени на активную задачу. Очевидно что такое может делаться только в ОС, допускающих задачи с равным приоритетом.

Я использую uCOS, а в ней не допускается двух задач с одинаковым приоритетом. Соответственно - всё время CPU всегда получает задача с наивысшим приоритетом, и

менее приоритетная задача может получить время только если все более приоритетные уйдут в ожидание. Это более простая организация ОС, мне её хватает.

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

и собственно - переключение контекста (передача управления с переключением стека и рабочих переменных ОС).

 

Так вот решедулинг выполняется

во-первых:

при выполнении любой операции ОС с объектами синхронизации ОС (семафорами, мьютексами и пр.). Т.е. - при вызове функций ОС ЗанятьСемафор(), ОсвободитьСемафор(), и т.п.

во-вторых:

в функции таймера, который отсчитывает счётчики времени приостановки задач (OSTimeDelay(N_тактов_таймера)) вызванные задачами для создания паузы в выполнении задач.

 

Решедулинг определяет - изменилась-ли текущая high-priority task? И, если изменилась, ставит запрос PendSV.

Например - задача вызвала ОжиданиеСемафора() который в настоящий момент занят. Тогда она будет переведена в состояние Wait (с опциональной привязкой дескриптора задачи к

семафору). Соответственно - нужно найти новую текущую high-priority task. Решедулинг просматривает список задач находящихся в активном состоянии (хотя-бы одна должна быть,

всегда имеется фоновая Idle-задача ОС, на самом низшем приоритете, которая никогда не должна уходить в Wait (не должна вызывать никаких функций ожидания ОС)), выбирает

имеющую высший приоритет и ставит запрос PendSV. То же самое происходит в любом другом вызове функций ОсвободитьСемафор() или Занять/ОсвободитьМьютекс() или

ПриостановитьЗадачуНаNТиков() и т.п.

 

Само переключение контекста делается всегда в одном месте - в ISR PendSV. Это избавляет от необходимости запрета прерываний на время работы функции переключения контекста -

она может быть прервана любым ISR и соответственно - совсем не мешает аппаратным прерываниям.

 

Единственное, что делается в системном таймере (относительно переключения задач ОС) - это декремент счётчиков задержек выполнения задач (если задача вызвала

ожидание функцией OSTimeDelay(N_тактов_таймера) и если какой-то из этих счётчиков обнулился, соответствующая задача переходит из состояния DELAYED в состояние ACTIVE и

вызывается Решедулинг().

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


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

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

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


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

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

Я думаю - Вы немного путаете. Вам наверное нужна обычная вытесняющая многозадачность, но с возможностью существования равноприоритетных задач.

И только если задача с равным приоритетом не отдаёт сама время CPU (вызывая одну из функций ожидания объекта синхронизации ОС), она может быть

переключена на следующую с таким-же приоритетом.

Приоритеты по-любому должны быть. Хотя-бы у фонового IDLE-процесса должен быть приоритет ниже, чем у любого другого процесса.

 

Или вам нужна корпоративная многозадачность?

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


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

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

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


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

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

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


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

таймер - это ограничение сверху, чтобы если задача не отдает процессор, его у нее отберут принудительно, спасибо за пояснения!

Только если для задачи с таким-же приоритетом могут отобрать! К примеру в uCOS, так как у всех задач уникальные приоритеты, процессор у активной задачи заберут

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

у более приоритетной задачи истечёт время приостановки задачи по OSTimeDelay().

 

И всегда есть самый низкоприоритетный IDLE-процесс, аккумулирующий все неиспользованные такты CPU в инструкциях WFE/WFI или в цикле вычисления загрузки CPU.

 

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

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

и когда отпущенное ей время истечёт, самостоятельно передать управление другой задаче.

В вытесняющей эти функции берёт на себя шедулер.

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

К тому-же в первом варианте будут сложности с организацией семафоров, которые могут освобождаться в ISR.

 

PS: Вообще тема неверно озаглавлена. Ибо имеет отношение к STM ровно такое-же, как к любому другому Cortex-M, а к Keil - вообще никакого...

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


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

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

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

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

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

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

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

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

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

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