Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ***********************************************************
- // ** NyaOS Sample **
- // ***********************************************************
- // http://teplofizik.diary.ru/p179560849.htm
- // Объявление таблиц, запуск ОС и добавление процессов.
- #include "nyaos.h"
- #include <string.h>
- // Заглушка на всякий случай, если вдруг какому-либо процессу захочется выйти с помощью записи LR в PC.
- void nyaos_Stub(void);
- // Настройка системного таймера
- void SysTickInit(void);
- // Максимальное количество процессов
- const uint32_t ProcessMaxCount = PROCESS_MAX_COUNT;
- // Размер стека
- const uint32_t StackSize = STACK_SIZE;
- // Запущено?
- volatile uint32_t Started;
- // Текущий процесс
- volatile uint32_t CurrentProcess;
- // Номер процесса (для назначения новых)
- volatile uint32_t PIDCounter;
- // Таблица процессов
- volatile TProcess ProcessTable[PROCESS_MAX_COUNT];
- // Таблица контекстов
- volatile TProcessContext ContextTable[PROCESS_MAX_COUNT];
- // Куча для стеков
- volatile uint8_t StackHeap[PROCESS_MAX_COUNT][STACK_SIZE];
- // Процесс для простоя.
- static int nyaos_Idle(uint32_t Argument)
- {
- while (1)
- {
- }
- }
- // Получить адрес стека по умолчанию для слота.
- // Не проверяется допустимость номера!
- // Аргументы: 1
- // Slot: номер слота
- // Результат: указатель стека.
- static uint32_t nyaos_GetDefaultSP(uint32_t Slot)
- {
- return (uint32_t)&(StackHeap[Slot][StackSize - 4]);
- }
- // Сформировать стек прерывания и вернуть на него указатель
- // Аргументы: 1
- // Context: указатель на структуру контекста процесса
- static TInterruptStackFrame * nyaos_AddStackFrame(volatile TProcessContext * Context)
- {
- TInterruptStackFrame * StackFrame;
- if(Context->SP == 0) return 0;
- Context->SP -= sizeof(TInterruptStackFrame);
- StackFrame = (TInterruptStackFrame *)Context->SP;
- // Настроить регистры по умолчанию
- StackFrame->R0 = 0;
- StackFrame->R1 = 0;
- StackFrame->R2 = 0;
- StackFrame->R3 = 0;
- StackFrame->R12 = 0;
- // Адрес возврата: заглушка, чтоб ничего не поломалось. Туда можно добавить функцию завершния процесса
- StackFrame->LR = (uint32_t)&nyaos_Stub;
- StackFrame->PC = (uint32_t)&nyaos_Stub;
- // Состояние статуса по-умолчанию
- StackFrame->CPSR = DEFAULT_CPSR;
- return StackFrame;
- }
- // Инициализация таблиц, выделение процессам адресов вершин стека
- // Аргументы: нет
- // Результат: нет
- static void nyaos_InitTables(void)
- {
- volatile TProcess * Process;
- volatile TProcessContext * Context;
- int i;
- for(i = 0; i < ProcessMaxCount; i++)
- {
- Process = &ProcessTable[i];
- Context = &ContextTable[i];
- Process->Context = Context;
- // Задать начальный SP
- Context->SP = nyaos_GetDefaultSP(i);
- }
- }
- // Добавить процесс
- // Аргументы:
- // EntryPoint: точка входа;
- // Argument: аргумент, которй будет передан в функцию;
- // Flags: параметры создания процесса.
- // Результат: код ошибки
- int nyaos_AddProcess(char * Name, void * EntryPoint, uint32_t Argument, uint32_t Flags)
- {
- volatile TProcess * Process = 0;
- volatile TProcessContext * Context;
- volatile TInterruptStackFrame * StackFrame;
- int i = 0;
- // Чтобы добавить процесс, нужно заполнить таблицу его контекста.
- // Но сначала найдём свободную запись о процессе
- for(i = 0; i < ProcessMaxCount; i++)
- {
- // Очередную запись проверим
- Process = &ProcessTable[i];
- if(Process->PID == 0)
- {
- // Нашёлся свободный слот
- break;
- }
- // Уберём адрес как свидетельство занятости
- Process = 0;
- }
- // Если не нашлось, сообщим об этом
- if(Process == 0) return E_PROCESS_MAX_COUNT;
- // Новый номер процесса
- PIDCounter++;
- Process->PID = PIDCounter;
- Process->Flags = 0;
- Process->Name = Name;
- // Настроим контекст
- Context = &ContextTable[i];
- // Указатель стека - в начальное положение
- Context->SP = nyaos_GetDefaultSP(i);
- // Указатель на стек прерывания
- StackFrame = nyaos_AddStackFrame(Context);
- // Установим PC на точку входа
- StackFrame->PC = (uint32_t)EntryPoint;
- // Аргумент в R0
- StackFrame->R0 = Argument;
- // R8-R11 выставим в 0
- memset((void *)&Context->Rother[0], 0, sizeof(Context->Rother));
- return E_PROCESS_CREATED;
- }
- // Инициализация ОС
- // Аргументы: нет
- // Результат: нет
- void nyaos_Init(void)
- {
- SysTickInit();
- nyaos_InitTables();
- // Добавим пустой процесс
- nyaos_AddProcess("Idle", &nyaos_Idle, 0, 0);
- CurrentProcess = 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement