Advertisement
teplofizik

nyaos_core.s (12)

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