Ладно. Наплюём пока на акселерометр (он нам понадобится потом). Сейчас главная задача — сделать примитивную вытесняющую ОС. Памяти дофига, можно не жадничать.
ОС я ни разу не писал, но надо ж с чего-то начинать. А для изучения асма и контроллера это самое то. Пока читать литературу не буду, попробую сообразить сам.
читать дальшеЧто для самого-самого базового нам понадобится?
1. Системный таймер.
В прерывании должно происходить переключение контекста. То есть сохраняться все регистры (R0-R15 и CPSR) для текущей задачи и загружаться для следующей. Самое классное то, что часть работы сделает сам процессор. Как я уже говорил — основные регистры (R0-R3,R12,LR,PC,CPSR) при появлении прерывания кладутся в стек, откуда их можно преспокойно скопипастить. И заменить на иные. И процессор их благополучно вернёт, как будто ничего и не случалось.
2. Память под контекст задачи и для каждой свой стек. Плюс структура для идентификации процессов и их переключения.
Возьмём самый первый пустой проект, настроим стандартную библиотеку и системный таймер.
Единственное замечание: ОС — это средство, потому оно должно быть в побочных файлах. А главным файлом будет main.c, откуда ОС будет запускаться и где будут добавлены сами процессы.
В принципе, никто не запрещает сделать то же самое с асмовскими функциями, но так более наглядно, как мне кажется. С прикладной точки зрения.
И да, ОС у нас будет называться NyaOS. Что, в общем-то, было очевидно с самого начала. Название эмулятора-дизассемблера NyARM я тоже застолблю за себя =D
Запись в таблице процессов будет содержать идентификатор процесса, указатель на имя процесса и поле флагов. Таблица будет состоять из наперёд заданного количества элементов. Процесс с нулевым PID не участвует в работе и пропускается. При инициализации все записи имеют PID = 0.
Стек пусть будет у всех одинаков по размеру и задаваться пока в настройках проекта. Тогда контекст процесса будет выглядеть так:
В принципе, можно ещё для удобства создать структуру, описывающую состояние вершины стека после попадания в прерывание:
Сделаем таблицы процессов и контекста, например, на 10 элементов.
Добавим пустой процесс в нулевой слот, который будет работать, если в будущем появятся флаги ожидания и все процессы будут что-то ждать. При наличии активных процессов этот процесс будет диспетчером игнорироваться. Тут же можно будет считать время простоя.
При добавлении процесса:
1. Ищем свободный слот в таблице;
2. Назначаем PID;
3. Запоминание название;
4. Назначаем вершину стека (из имеющейся кучи, хотя в приципе компилятор позволяет динамически выделять её);
5. Записываем в регистры общего назначения нули (в таблицу в стеке, конечно же);
6. В регистр R0 записываем аргумент к задаче (там же);
7. В LR пишем адрес заглушки (Там инструкция "B ."), чтоб если вышло из процесса, так хоть не куда попало, а вполне контролируемо. В будущем можно добавить возврат на функцию аварийного завершения процесса.
8. Инициализируем CPSR в таблице числом 0x01000000, то есть установлен только T-бит, ответственный за режим. Иначе будет плохо.
9. В область памяти, ответственную за PC, запишем точку входа в процесс.
Вот и всё. Все остальные дела сделает диспетчер при наступлении очередного прерывания =)
Что должен делать диспетчер?
1. Посмотреть номер текущего слота (или можно хранить прям указатель на него) и записать туда регистры R4-R11 и сохранить SP, используя только регистры R0-R3 и R12. Напомню, что их ядро автоматически сохраняет в стек. После чего появляется свобода использования остальных регистров;
2. Найти следующий процесс. Пока они не имеют никаких флагов ожидания, так что это будет просто первый попавшийся следующий в таблице процесс с ненулевым PID. Если таковых после полного обхода таблицы не обнаружилось, выбираем заранее созданный процесс в слоте ноль (Idle);
3. Меняем номер активного процесса в переменной;
4. Загружаем адрес записи контекста;
5. Загружаем оттуда новый указатель стека;
6. Загружаем старшие регистры копипастом из таблицы (используя R0-R3, R12);
7. Выходим из прерывания.
При этом выполнение перейдёт в выбранный процесс.
Сделав два процесса, моргающих светодиодами, можно понаблюдать их синхронную работу. Диспетчер работает.
Вот файлы:
main.c
nyaos.h - объявления таблиц;
nyaos.c - инициализация таблиц, добавление процесса;
nyaos_core.s - диспетчер;
Проект целиком.<< Предыдущее Следующее >>
@темы:
arm,
программизмы,
электроника,
ассемблер,
stm32f4discovery,
stm32