Advertisement
teplofizik

nyaos_core.s (10)

Aug 13th, 2012
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; ***********************************************************
  2. ; **                    NyaOS Sample                       **
  3. ; ***********************************************************
  4. ; http://teplofizik.diary.ru/p179620030.htm
  5.  
  6.     AREA    RAM, DATA, NOINIT, READWRITE, ALIGN=3
  7.    
  8. ; Указатель стека главного процесса
  9. SPMain      DCD 0
  10.  
  11.     AREA    |.text|, CODE, READONLY
  12.  
  13.             EXPORT nyaos_Stub
  14.             EXPORT nyaos_Start
  15.            
  16.             ; Прерывания
  17.             EXPORT SysTick_Handler
  18.             EXPORT SVC_Handler
  19.            
  20.             IMPORT ProcessTable
  21.             IMPORT ContextTable
  22.             IMPORT CurrentProcess
  23.             IMPORT ProcessMaxCount
  24.            
  25.             IMPORT SWI_Table   ; swi_table.s
  26.             IMPORT SWI_Count   ; swi_table.s
  27.             IMPORT SWI_ChCount ; swi_table.s
  28.            
  29.             GET nyaos.inc
  30.             GET system.inc
  31.  
  32. ; Получить номер текущего процесса
  33. ; Аргументы: нет
  34. ; Результаты: номер слота
  35. ; Используемые регистры: LR, R0
  36. disp_GetSlotIndex PROC
  37.                   ; Загрузим номер текущего процесса (по таблице)
  38.                   MOV32 R0, CurrentProcess
  39.                   LDR   R0, [R0] ; Прочитаем номер процесса
  40.                  
  41.                   BX    LR
  42.                   ENDP
  43.  
  44. ; Установить номер текущего процесса
  45. ; Аргументы: 1
  46. ;  R0: номер слота
  47. ; Результаты: нет
  48. ; Используемые регистры: LR, R1
  49. disp_SetSlotIndex PROC
  50.                   MOV32 R1, CurrentProcess
  51.                   STR   R0, [R1] ; Запишем номер процесса
  52.                  
  53.                   BX    LR
  54.                   ENDP
  55.  
  56. ; Сохранение состояния текущей задачи
  57. ; Аргументы: 1
  58. ;  R0: номер текущего слота
  59. ; Результаты: нет
  60. ; Используемые регистры: LR, R0, R1, R2, R3
  61. disp_SaveContext PROC
  62.                  ; Загрузим адрес таблицы контекстов
  63.                  MOV32 R1, ContextTable
  64.                
  65.                  ; Выберем нужную запись
  66.                  MOV   R2, #CONTEXT_SIZE
  67.                  MUL   R0, R0, R2
  68.                  ADD   R1, R1, R0
  69.                
  70.                  ; Сохраним состояние старших регистров
  71.                  STR   SP,  [R1, #CONT_SP]
  72.                  STR   R4,  [R1, #CONT_R4]
  73.                  STR   R5,  [R1, #CONT_R5]
  74.                  STR   R6,  [R1, #CONT_R6]
  75.                  STR   R7,  [R1, #CONT_R7]
  76.                  STR   R8,  [R1, #CONT_R8]
  77.                  STR   R9,  [R1, #CONT_R9]
  78.                  STR   R10, [R1, #CONT_R10]
  79.                  STR   R11, [R1, #CONT_R11]
  80.                
  81.                  BX   LR
  82.                  ENDP
  83.                  
  84. ; Чтение состояния текущей задачи
  85. ; Аргументы: 1
  86. ;  R0: номер текущего слота
  87. ; Результаты: нет
  88. ; Используемые регистры: LR, R0, R1, R2
  89. disp_LoadContext PROC
  90.                 ; Выбираем контекст
  91.                 MOV32 R1, ContextTable
  92.                 MOV   R2, #CONTEXT_SIZE
  93.                 MUL   R2, R0, R2
  94.                 ADD   R1, R2
  95.                
  96.                 ; Загружаем регистры и указатель стека
  97.                 LDR   SP,  [R1, #CONT_SP]
  98.                 LDR   R4,  [R1, #CONT_R4]
  99.                 LDR   R5,  [R1, #CONT_R5]
  100.                 LDR   R6,  [R1, #CONT_R6]
  101.                 LDR   R7,  [R1, #CONT_R7]
  102.                 LDR   R8,  [R1, #CONT_R8]
  103.                 LDR   R9,  [R1, #CONT_R9]
  104.                 LDR   R10, [R1, #CONT_R10]
  105.                 LDR   R11, [R1, #CONT_R11]
  106.                 BX    LR
  107.                 ENDP
  108.  
  109. ; Расчёт задержек
  110. ; Аргументы: 0
  111. ; Результат: нет
  112. ; Используемые регистры: LR, R0
  113. disp_CalcDelay  PROC
  114.                 ; Пробежимся по таблице, посмотрим, есть ли задержки
  115.                 MOV R0, #0
  116.                
  117.                 ; Загрузим таблицу процессов
  118.                 MOV32 R2, ProcessTable
  119.                
  120.                 ; Загрузим ограничение на количество
  121.                 MOV32 R4, ProcessMaxCount
  122.                 LDR   R4, [R4]
  123.                
  124. __next_proc
  125.                 ; Допустимый номер процесса?
  126.                 CMP   R0, R4
  127.                 BPL   __del_exit
  128.                
  129.                 LDR   R1, [R2, #PROC_FLAGS] ; Process->Flags
  130.                
  131.                 ; Проверяем программную задержку (выставлена -> обработаем)
  132.                 TST   R1, #DELAY_MASK
  133.                 BEQ   __continue
  134.                
  135.                 ; Вычтем из поля Event единицу
  136.                 LDR   R1, [R2, #PROC_EVENT] ; Process->Event
  137.                 SUBS  R1, #1
  138.                 STR   R1, [R2, #PROC_EVENT] ; Process->Event
  139.                
  140.                 ; Если всё ещё больше или равно 0, идём дальше
  141.                 BPL   __continue
  142.                
  143.                 ; Минус. Задержка кончилась.
  144.                 ; Снимаем флаг задержки
  145.                 LDR   R1, [R2, #PROC_FLAGS] ; Process->Flags
  146.                 BIC   R1, #DELAY_MASK
  147.                 STR   R1, [R2, #PROC_FLAGS] ; Process->Flags
  148.                
  149. __continue
  150.                 ; Следующий процесс
  151.                 MOV   R1, #PROCESS_SIZE
  152.                 ADD   R2, R1
  153.                
  154.                 ADD   R0, #1
  155.                 B     __next_proc
  156.                
  157. __del_exit
  158.                 BX   LR
  159.                 ENDP
  160.  
  161. ; Поиск следующей задачи
  162. ; Аргументы: 1
  163. ;  R0: номер текущего слота
  164. ; Результат: номер следующего слота
  165. ; Используемые регистры: LR, R0, R1, R2, R3, R4, R5, R6, R7
  166. disp_FindNext   PROC
  167.                 ; Запомним номер процесса
  168.                 MOV   R3, R0
  169.                
  170.                 ; Загрузим таблицу процессов
  171.                 MOV32 R2, ProcessTable
  172.                 ; И размер одной записи...
  173.                 MOV   R5, #PROCESS_SIZE
  174.                
  175.                 ; Загрузим ограничение на количество
  176.                 MOV32 R4, ProcessMaxCount
  177.                 LDR   R4, [R4]
  178.                
  179.                 ; Ищем свободный PID
  180. _proc_next
  181.                 ADD   R0, #1
  182.                
  183.                 ; Проверим на границу диапазона
  184.                 CMP   R0, R4
  185.                 ; Загрузим 0, если вылезли (0 для Idle)
  186.                 IT    EQ
  187.                 MOVEQ R0, #0
  188.                
  189.                 ; Сравним с номером, с которого начинали
  190.                 CMP   R0, R3
  191.                 ; Если он - загрузим процесс Idle (0).
  192.                 ITT   EQ
  193.                 MOVEQ R0, #0
  194.                 BEQ   _proc_found
  195.                
  196.                 ; Если это процесс Idle, пропускаем.
  197.                 CMP   R0, #0
  198.                 BEQ   _proc_next
  199.                
  200.                 ; Нет, не он. Проверим PID
  201.                 ; Считаем смещение до элемента
  202.                 MOV   R6, R0
  203.                 MUL   R6, R6, R5
  204.                 ADD   R6, R2
  205.                
  206.                 ; Грузим PID
  207.                 LDR   R7, [R6, #PROC_PID]
  208.                
  209.                 ; Если ноль, ищем дальше.
  210.                 CMP   R7, #0
  211.                 BEQ   _proc_next
  212.                
  213.                 ; Проверим регистр флагов:
  214.                 LDR   R7, [R6, #PROC_FLAGS] ; Process->Flags
  215.                
  216.                 ; Проверяем программную задержку (выставлена -> мимо)
  217.                 TST   R7, #DELAY_MASK
  218.                 BNE   _proc_next
  219.                
  220.                 ; Проверяем ожидание события
  221.                 TST   R7, #EVENT_MASK
  222.                 BEQ   _proc_found           ; События нет, пропускаем проверку события
  223.                
  224.                 ; Проверяем наступление события:
  225.                 LDR   R7, [R6, #PROC_EVENT] ; Process->Event
  226.                 LDR   R8, [R7]              ; *(Process->Event)
  227.                
  228.                 CMP   R8, #0
  229.                
  230.                 ; Если не наступило - ищем дальше
  231.                 BEQ   _proc_next
  232.                
  233.                 ; Событие наступило.
  234.                
  235.                 ; В R0 - код события, не трогаем его
  236.                
  237.                 ; Запишем ноль в переменную как знак, что
  238.                 ; событие обработано.
  239.                 MOV   R1, #0
  240.                 STR   R1, [R7]
  241.                
  242.                 ; Запишем в контекст процесса, в R0 код события
  243.                 ; Указатель на контекст...
  244.                 LDR   R1, [R6, #PROC_CONTEXT]
  245.                 ; Указатель на SP
  246.                 LDR   R1, [R1, #CONT_SP]
  247.                
  248.                 ; Запишем по SP + 0
  249.                 STR   R8, [R1]
  250.  
  251.                 ; Снимем флаг события.
  252.                 LDR   R7, [R6, #PROC_FLAGS] ; Process->Flags
  253.                 BIC   R7, #EVENT_MASK
  254.                 STR   R7, [R6, #PROC_FLAGS] ; Process->Flags
  255.                
  256. _proc_found     ; Процесс выбран
  257.                 BX    LR
  258.                 ENDP
  259.  
  260. ; Диспетчер
  261. ; Переключение задач
  262. SysTick_Handler PROC
  263.                 ; Запомним код выхода в обычный режим
  264.                 MOV R12, LR
  265.                
  266.                 ; Номер текущего слота
  267.                 BL    disp_GetSlotIndex
  268.                
  269.                 ; Если не надо сохранять, не сохраняем...
  270.                 CMP   R0, #0xFF000000
  271.                 BEQ   _sysh_start
  272.                
  273.                 ; Сохранить контекст
  274.                 BL    disp_SaveContext
  275.                
  276.                 ; Посчитаем программные задержки для всех процессов
  277.                 BL    disp_CalcDelay
  278.  
  279.                 ; Номер текущего слота
  280.                 BL    disp_GetSlotIndex
  281.                
  282.                 ; Запомним номер
  283.                 MOV   R3, R0
  284.                
  285.                 B     _sysh_loadptable
  286.                
  287. _sysh_start
  288.                 ; Cохраним указатель стека
  289.                 MOV32 R0, SPMain
  290.                 STR   SP, [R0]
  291.                
  292.                 ; Текущий Process: 0
  293.                 MOV   R3, #0
  294.                
  295. _sysh_loadptable
  296.                 ; получить номер следующей задачи
  297.                 MOV   R0, R3
  298.                 BL    disp_FindNext
  299.                
  300.                 ; Сохраним номер выбранного процесса
  301.                 BL    disp_SetSlotIndex
  302.                
  303.                 ; Загрузим контекст
  304.                 BL    disp_LoadContext
  305.                
  306.                 ; Выход из прерывания уже по новому PC
  307.                 BX  R12
  308.                 ENDP
  309.  
  310. ; Обработчик программного прерывания
  311. SVC_Handler PROC
  312.             PUSH {R8-R11}
  313.             MOV   R12, LR
  314.            
  315.             ; Получение номера прерывания
  316.             LDR   R11, [SP, #0x28] ; PC
  317.             LDRB  R11, [R11, #-2]  ; Младший байт инструкции (номер)
  318.  
  319.             ; Проверим номер на допустимость (а то улетим куда)
  320.             MOV32 R8, SWI_Count
  321.             LDR   R8, [R8]
  322.            
  323.             ; Если много - выходим.
  324.             CMP   R11, R8
  325.             ITT   GE
  326.             POPGE {R8-R11}
  327.             BXGE  R12
  328.            
  329.             ; Сохраним номер для проверки дальнейшей
  330.             PUSH {R11}
  331.            
  332.             ; Умножим номер на 4, получим смещение.
  333.             LSL   R11, #2
  334.            
  335.             ; И прибавим к началу таблицы
  336.             MOV32 R8, SWI_Table
  337.            
  338.             ; Загрузим адрес функции
  339.             LDR   R11, [R8, R11]
  340.            
  341.             ; Сохраним R12 (код возврата)
  342.             PUSH {R12}
  343.            
  344.             ; Вызов функции
  345.             BLX   R11
  346.            
  347.             ; Вернём R12 (код возврата)
  348.             POP  {R12}
  349.            
  350.             ; Вытащим номер обратно в R1
  351.             POP  {R1}
  352.            
  353.             ; Скопипастим R0 обратно в стек
  354.             STR   R0, [SP, #0x10]
  355.            
  356.             POP  {R8-R11}
  357.            
  358.             ; Проверим, надо ли менять процесс или пусть остаётся
  359.             ; Задано количество элементов, после выполнения которых требуется смена
  360.             ; процесса. Проверим, не один из них ли?
  361.             MOV32 R2, SWI_ChCount
  362.             LDR   R2, [R2]
  363.            
  364.             ; Если номер больше порогового, то выходим из прерывания, не меняя процесс.
  365.             CMP   R1, R2
  366.             IT    GE
  367.             BXGE  R12
  368.            
  369.             ; Смена процесса.
  370.             ; Номер текущего слота
  371.             BL    disp_GetSlotIndex
  372.                
  373.             ; Если не надо сохранять, не сохраняем...
  374.             CMP   R0, #0xFF000000
  375.             BEQ   _svch_start
  376.                
  377.             ; Запомним номер
  378.             MOV   R3, R0
  379.                
  380.             ; Сохранить контекст
  381.             BL    disp_SaveContext
  382.                
  383.             B     _svch_loadptable
  384.                
  385. _svch_start
  386.             ; Cохраним указатель стека
  387.             MOV32 R0, SPMain
  388.             STR   SP, [R0]
  389.                
  390.             ; Текущий Process: 0
  391.             MOV   R3, #0
  392.                
  393. _svch_loadptable
  394.             ; получить номер следующей задачи
  395.             MOV   R0, R3
  396.             BL    disp_FindNext
  397.                
  398.             ; Сохраним номер выбранного процесса
  399.             BL    disp_SetSlotIndex
  400.                
  401.             ; Загрузим контекст
  402.             BL    disp_LoadContext
  403.            
  404.             ; Выход из прерывания
  405.             BX    R12
  406.             ENDP
  407.  
  408. ; Заглушка на всякий случай, если вдруг какому-либо процессу захочется выйти с помощью записи LR в PC.
  409. ; В дальнейшем может быть добавлен код для каноничного завершения такого процесса с ошибкой.
  410. ; Аргументы: нет
  411. ; Результаты: нет
  412. nyaos_Stub      PROC
  413.                 B .
  414.                 ENDP
  415.            
  416. ; Запуск ОС
  417. ; Аргументы: нет
  418. ; Результаты: нет
  419. nyaos_Start PROC
  420.             ; Разрешить прерывания от таймера
  421.             MOV R0, #1
  422.             BL  SysTickInterruptEnable
  423.            
  424.             ; По прерыванию выполнение перейдёт к процессу
  425. __mainloop
  426.  
  427.             ; На очередной круг
  428.             B __mainloop
  429.            
  430.             ENDP
  431.  
  432.     END
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement