Advertisement
teplofizik

nyaos.c (10)

Aug 13th, 2012
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.00 KB | None | 0 0
  1. // ***********************************************************
  2. // **                    NyaOS Sample                       **
  3. // ***********************************************************
  4. // http://teplofizik.diary.ru/p179620030.htm
  5.  
  6. // Объявление таблиц, запуск ОС и добавление процессов.
  7.  
  8. #include "nyaos.h"
  9.  
  10. #include <string.h>
  11.  
  12. // Заглушка на всякий случай, если вдруг какому-либо процессу захочется выйти с помощью записи LR в PC.
  13. void nyaos_Stub(void);
  14.  
  15. // Настройка системного таймера
  16. void SysTickInit(void);
  17.  
  18. // Максимальное количество процессов
  19. const uint32_t ProcessMaxCount = PROCESS_MAX_COUNT;
  20.  
  21. // Максимальное количество зарегистрированных событий
  22. const uint32_t EventMaxCount   = EVENT_MAX_COUNT;
  23.  
  24. // Размер стека
  25. const uint32_t StackSize       = STACK_SIZE;
  26.  
  27. // Текущий процесс
  28. volatile uint32_t        CurrentProcess;
  29.  
  30. // Номер процесса (для назначения новых)
  31. volatile uint32_t        PIDCounter;
  32.  
  33. // Таблица процессов
  34. volatile TProcess        ProcessTable[PROCESS_MAX_COUNT];
  35.  
  36. // Таблица контекстов
  37. volatile TProcessContext ContextTable[PROCESS_MAX_COUNT];
  38.  
  39. // Куча для стеков
  40. volatile uint8_t         StackHeap[PROCESS_MAX_COUNT][STACK_SIZE];
  41.  
  42. // Таблица зарегистрированных событий
  43. volatile TEvent          EventTable[EVENT_MAX_COUNT];
  44.  
  45. // Процесс для простоя.
  46. static int nyaos_Idle(uint32_t Argument)
  47. {
  48.     while (1)
  49.     {
  50.        
  51.     }
  52. }
  53.  
  54. // Получить адрес стека по умолчанию для слота.
  55. // Не проверяется допустимость номера!
  56. // Аргументы: 1
  57. //  Slot: номер слота
  58. // Результат: указатель стека.
  59. static uint32_t nyaos_GetDefaultSP(uint32_t Slot)
  60. {
  61.     return (uint32_t)&(StackHeap[Slot][StackSize - 4]);
  62. }
  63.  
  64. // Сформировать стек прерывания и вернуть на него указатель
  65. // Аргументы: 1
  66. //  Context: указатель на структуру контекста процесса
  67. static TInterruptStackFrame * nyaos_AddStackFrame(volatile TProcessContext * Context)
  68. {
  69.     TInterruptStackFrame * StackFrame;
  70.    
  71.     if(Context->SP == 0) return 0;
  72.    
  73.     Context->SP -= sizeof(TInterruptStackFrame);
  74.     StackFrame = (TInterruptStackFrame *)Context->SP;
  75.    
  76.     // Настроить регистры по умолчанию
  77.     StackFrame->R0 = 0;
  78.     StackFrame->R1 = 0;
  79.     StackFrame->R2 = 0;
  80.     StackFrame->R3 = 0;
  81.     StackFrame->R12 = 0;
  82.    
  83.     // Адрес возврата: заглушка, чтоб ничего не поломалось. Туда можно добавить функцию завершния процесса
  84.     StackFrame->LR = (uint32_t)&nyaos_Stub;
  85.     StackFrame->PC = (uint32_t)&nyaos_Stub;
  86.    
  87.     // Состояние статуса по-умолчанию
  88.     StackFrame->CPSR = DEFAULT_CPSR;
  89.    
  90.     return StackFrame;
  91. }
  92.  
  93. // Инициализация таблиц, выделение процессам адресов вершин стека
  94. // Аргументы: нет
  95. // Результат: нет
  96. static void nyaos_InitTables(void)
  97. {
  98.     volatile TProcess        * Process;
  99.     volatile TProcessContext * Context;
  100.     int                        i;
  101.    
  102.     for(i = 0; i < ProcessMaxCount; i++)
  103.     {
  104.         Process = &ProcessTable[i];
  105.         Context = &ContextTable[i];
  106.        
  107.         Process->Context = Context;
  108.        
  109.         // Задать начальный SP
  110.         Context->SP = nyaos_GetDefaultSP(i);
  111.     }
  112. }
  113.  
  114. // Получить запись зарегистрированного события по идентификатору
  115. // Аргументы: 1
  116. //  Event: идентификатор события
  117. // Результат: указатель на запись, если такая есть или ноль
  118. volatile TEvent * nyaos_GetEvent(EVENT Event)
  119. {
  120.     int i;
  121.    
  122.     for(i = 0; i < EventMaxCount; i++)
  123.     {
  124.         volatile TEvent * E = &EventTable[i];
  125.        
  126.         if(E->EventID == Event) return E;
  127.     }
  128.    
  129.     return 0;
  130. }
  131.  
  132. // Добавить процесс
  133. // Аргументы:
  134. //  EntryPoint: точка входа;
  135. //  Argument: аргумент, которй будет передан в функцию;
  136. //  Flags: параметры создания процесса.
  137. // Результат: код ошибки
  138. int nyaos_AddProcess(char * Name, void * EntryPoint, uint32_t Argument, uint32_t Flags)
  139. {
  140.     volatile TProcess             * Process = 0;
  141.     volatile TProcessContext      * Context;
  142.     volatile TInterruptStackFrame * StackFrame;
  143.     int                        i = 0;
  144.    
  145.     // Чтобы добавить процесс, нужно заполнить таблицу его контекста.
  146.     // Но сначала найдём свободную запись о процессе
  147.     for(i = 0; i < ProcessMaxCount; i++)
  148.     {
  149.         // Очередную запись проверим
  150.         Process = &ProcessTable[i];
  151.        
  152.         if(Process->PID == 0)
  153.         {
  154.             // Нашёлся свободный слот
  155.             break;
  156.         }
  157.            
  158.         // Уберём адрес как свидетельство занятости
  159.         Process = 0;
  160.     }
  161.    
  162.     // Если не нашлось, сообщим об этом
  163.     if(Process == 0) return E_PROCESS_MAX_COUNT;
  164.    
  165.     // Новый номер процесса
  166.     PIDCounter++;
  167.    
  168.     Process->PID = PIDCounter;
  169.     Process->Flags = 0;
  170.     Process->Name = Name;
  171.    
  172.     // Настроим контекст
  173.     Context = &ContextTable[i];
  174.    
  175.     // Указатель стека - в начальное положение
  176.     Context->SP = nyaos_GetDefaultSP(i);
  177.    
  178.     // Указатель на стек прерывания
  179.     StackFrame = nyaos_AddStackFrame(Context);
  180.    
  181.     // Установим PC на точку входа
  182.     StackFrame->PC = (uint32_t)EntryPoint;
  183.    
  184.     // Аргумент в R0
  185.     StackFrame->R0 = Argument;
  186.    
  187.     // R8-R11 выставим в 0
  188.     memset((void *)&Context->Rother[0], 0, sizeof(Context->Rother));
  189.    
  190.     return E_PROCESS_CREATED;
  191. }
  192.  
  193. // Инициализация ОС
  194. // Аргументы: нет
  195. // Результат: нет
  196. void nyaos_Init(void)
  197. {
  198.     SysTickInit();
  199.    
  200.     nyaos_InitTables();
  201.    
  202.     // Добавим пустой процесс
  203.     nyaos_AddProcess("Idle", &nyaos_Idle, 0, 0);
  204.    
  205.     // Магическая константа для предотвращения сохранения регистров в первый раз в диспетчере
  206.     CurrentProcess = 0xFF000000;
  207. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement